You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Leaflet中基于参考点实现图像旋转、缩放与平移匹配的问题

Leaflet图像叠加配准功能优化问题

我正在实现一个让用户将图像叠加到Leaflet地图的功能,流程是用户在图像和地图上各选择两个参考点(使用地图坐标),通过这四个点对图像进行旋转、缩放和平移,让图像匹配地图上的目标位置。目前旋转和缩放有初步效果但不理想,而且还没处理平移部分。相关代码如下:

const PlantEditDrawer = () => {
  const { isPlantEditDrawerOpen } = useDashBoardContext();
  const [mounted, setMounted] = useState(false);
  const { leafletMap } = useLeafletMapContext();
  const { north, east, south, west } = usePositionBoundsContext();
  const [firstImage, setFirstImage] = useState<L.LatLng>();
  const [secondImage, setSecondImage] = useState<L.LatLng>();
  const [firstMap, setFirstMap] = useState<L.LatLng>();
  const [secondMap, setSecondMap] = useState<L.LatLng>();
  const [isDone, setDone] = useState(false);
  // const [imageBounds, setImageBounds] = useState<number[]>()
  const imageRef = useRef<L.ImageOverlay>();

  useEffect(() => {
    if (mounted) return;
    setMounted(true);
  }, [mounted]);
  const handleSecondMapClick = useCallback(
    (e: LeafletMouseEvent) => {
      setSecondMap(e.latlng);
      leafletMap?.current!.off("click");
      setDone(true);
    },
    [leafletMap]
  );

  const handleSecondImageClick = useCallback(
    (e: LeafletMouseEvent) => {
      setSecondImage(e.latlng);
      if (imageRef.current && leafletMap?.current) {
        leafletMap.current.removeLayer(imageRef.current);
        leafletMap.current.on("click", handleSecondMapClick);
      }
    },
    [handleSecondMapClick, leafletMap]
  );

  const handleFirstMapClick = useCallback(
    (e: LeafletMouseEvent) => {
      setFirstMap(e.latlng);
      imageRef.current?.addTo(leafletMap?.current!);
      imageRef.current?.on("click", handleSecondImageClick);
      leafletMap?.current!.off("click");
    },
    [handleSecondImageClick, leafletMap]
  );

  const handleFirstImageClick = useCallback(
    (e: LeafletMouseEvent) => {
      setFirstImage(e.latlng);
      if (imageRef.current && leafletMap?.current) {
        imageRef.current.off("click");
        leafletMap.current.removeLayer(imageRef.current);
        leafletMap.current.on("click", handleFirstMapClick);
      }
    },
    [handleFirstMapClick, leafletMap]
  );


  useEffect(() => {
    if (!leafletMap?.current) return;
    const bounds = L.latLngBounds([
      [south, west],
      [north, east],
    ]);
    imageRef.current = L.imageOverlay(image, bounds, {
      interactive: true,
      opacity: 0.5,
    }).addTo(leafletMap.current);
    imageRef.current?.on("click", handleFirstImageClick);
  }, [east, leafletMap, north, south, west, mounted, handleFirstImageClick]);

  function calculateAngle(p1:any, p2:any) {
    const deltaX = p2.lng - p1.lng;
    const deltaY = p2.lat - p1.lat;
    return Math.atan2(deltaX, deltaY) * (180 / Math.PI);
}


  useEffect(() => {
    if (!isDone || !firstImage || !secondImage || !firstMap || !secondMap) return;
    //计算角度
    const mapAngle = calculateAngle(firstMap, secondMap)
    const imageAngle = calculateAngle(firstImage, secondImage)

    const rotationRequired = mapAngle - imageAngle;

    const firstImageLatLng = L.latLng(firstImage.lat, firstImage.lng);
    const secondImageLatLng = L.latLng(secondImage.lat, secondImage.lng);
    const imageDistance = firstImageLatLng.distanceTo(secondImageLatLng);

    const firstMapLatLng = L.latLng(firstMap.lat, firstMap.lng);
    const secondMapLatLng = L.latLng(secondMap.lat, secondMap.lng);
    const mapDistance = firstMapLatLng.distanceTo(secondMapLatLng);

    const scaleFactor = mapDistance / imageDistance;
    if (imageRef.current) {
      imageRef.current.addTo(leafletMap?.current!);
      const test = imageRef.current.getElement();
      test!.style.transformOrigin = "center";
      const { transform } = test!.style;
      test!.style.transform = `${transform} rotate(${rotationRequired}deg) scale(${scaleFactor})`;
    }
  }, [firstImage, firstMap, isDone, leafletMap, secondImage, secondMap]);

// 未添加返回值
}

内容的提问来源于stack exchange,提问作者Malxruxes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:40:05