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

Autodesk Forge+Google Map中Polyline绕ModelOrigin旋转偏移问题

问题:Autodesk Forge Geolocation扩展旋转Polyline时偏移过大

我正在使用Autodesk Forge的Geolocation扩展处理3D模型,并通过@react-google-maps/api在Google Map上展示。目前拥有3D世界坐标格式的polygon、经纬度格式的polyline,以及3D模型中心点modelOrigin。尝试让polyline与polygon以相同方式绕modelOrigin旋转,但polygon旋转正常,polyline旋转时偏移距离过大,会远离modelOrigin。

我使用Autodesk Forge Geolocation扩展的LL842LmvPoint方法将polyline的经纬度(lat和lng)转换为3D世界坐标,通过lmv2LL84Point方法转换回经纬度格式。

获取polygon(buildingProfile)坐标与modelOrigin的代码

const [yAxisLineLatLng, setYAxisLineLatLng] = useState<any>([ { "lat": 40.733288742831924, "lng": -74.15844074123018 }, { "lat": 40.73363656398297, "lng": -74.15844074123018 } ]);
const [initialBuildingProfile, setInitialBuildingProfile] = useState<any>([]);
const [initialBuildingProfileLatLng, setInitialBuildingProfileLatLng] = useState<any>([]);

useEffect(() => {
  if (!model) return;

  const modelBoundingBox = model.getBoundingBox();
  const { min, max } = modelBoundingBox;
  const profilePolygon = [
    {
      x: min.x,
      y: min.y,
    },
    {
      x: max.x,
      y: min.y,
    },
    {
      x: max.x,
      y: max.y,
    },
    {
      x: min.x,
      y: max.y,
    },
  ];
  const center = modelBoundingBox.center();
  const origin = new (Autodesk.Viewing.Private as any).LmvVector3(...defaultLocation);
  localCS.current = new (Autodesk.Extensions as any).Geolocation.LocalCS(
    origin,
    model.getData().refPointTransform,
    model.getUnitScale(),
    model.getData().placementWithOffset,
  );
  setInitialBuildingProfile(profilePolygon);
  setModelOrigin(center);
}, [model, defaultLocation]);

转换buildingProfile为经纬度的代码

useEffect(() => {
  updateInitialBuildingProfile();
}, [buildingProfile, isLoaded]);

function updateInitialBuildingProfile() {
  const buildingProfileLatLng = buildingProfile.map(function (point: any) {
    const thePoint = new (Autodesk.Viewing.Private as any).LmvVector3(
      point.x,
      point.y,
      0,
    );
    const geoLoc = localCS.current.lmv2LL84Point(thePoint);
    return { lat: geoLoc.y, lng: geoLoc.x };
  });
  setInitialBuildingProfileLatLng(buildingProfileLatLng);
}

地图渲染代码

<GoogleMap
  id="buildingOrientation"
  zoom={18}
  onLoad={googleMapLoaded}
  center={{ lat: defaultLocation[1], lng: defaultLocation[0] }}
  mapContainerStyle={{
    height: "440px",
    width: "100%",
  }}
  options={{
    rotateControl: false,
    draggable: false,
    mapTypeControl: false,
    streetViewControl: false,
    fullscreenControl: false,
    tilt: 0,
  }}
>
  <PolygonF
    paths={initialBuildingProfileLatLng}
    options={{
      strokeColor: "#26282A",
      strokeOpacity: 1,
      strokeWeight: 2,
      fillColor: "#5B5C5E",
      fillOpacity: 1,
    }}
  />
  <Polyline
    options={{
      strokeColor: "red",
      strokeOpacity: 1.0,
      strokeWeight: 2,
    }}
    path={yAxisLineLatLng}
  />
</GoogleMap>;

初始渲染结果正常,但旋转后出现问题。

旋转polygon的代码

// function to rotate the squire polygon on a map.
function rotatePolygon(angle) {
  const coords = initialBuildingProfile.map((point: any) => {
    const rotatedPoint = rotatePoint(point, modelOrigin, angle);
    return { x: rotatedPoint.x, y: rotatedPoint.y };
  });

  return coords;
}

function rotatePoint(point: any, origin: any, angle: any) {
  const angleRad = -(angle * Math.PI) / 180.0;
  return {
    x:
      Math.cos(angleRad) * (point.x - origin.x) -
      Math.sin(angleRad) * (point.y - origin.y) +
      origin.x,
    y:
      Math.sin(angleRad) * (point.x - origin.x) +
      Math.cos(angleRad) * (point.y - origin.y) +
      origin.y,
  };
}

旋转polyline的代码

function rotatePolyline(polyline: any, angle: any) {
  if (!modelOrigin) return;
  const polyline = yAxisLineLatLng;

  const polyline3D = polyline.map((point: any) => {
    const point3D = localCS.current.LL842LmvPoint({ x: point.lng, y: point.lat });
    return { x: point3D.x, y: point3D.y };
  });

  const rotatedPolyline3D = polyline3D.map((point: any) =>
    rotatePoint(point, modelOrigin, angle),
  );

  const rotatedPolylineLatLng = rotatedPolyline3D.map((point: any) => {
    const pointLatLng = localCS.current.lmv2LL84Point(
      new (Autodesk.Viewing.Private as any).LmvVector3(point.x, point.y, point.z),
    );
    return { lat: pointLatLng.y, lng: pointLatLng.x };
  });

  return rotatedPolylineLatLng;
}

触发旋转的代码

const newCoords = rotatePolygon(15);
setBuildingProfile(newCoords);

const newAxis = rotatePolyline(15);
setYAxisLineLatLng(newAxis);

旋转15度后,polygon显示正常,但polyline远离modelOrigin,与预期结果不符。


解决方案

问题出在旋转Polyline时的坐标转换逻辑以及rotatePolyline函数的参数覆盖错误,具体修正如下:

1. 修复参数覆盖问题

rotatePolyline函数内重新声明const polyline = yAxisLineLatLng;覆盖了传入参数,导致每次旋转都使用初始坐标而非最新值,删除这行代码:

function rotatePolyline(polyline: any, angle: any) {
  if (!modelOrigin) return;
  // 移除该行:const polyline = yAxisLineLatLng;
  // ... 后续代码保留
}

2. 确保3D坐标Z轴一致性

转换Polyline到3D坐标时,显式设置Z值(默认0),避免后续转换偏差:

const polyline3D = polyline.map((point: any) => {
  const point3D = localCS.current.LL842LmvPoint({ x: point.lng, y: point.lat });
  return { x: point3D.x, y: point3D.y, z: point3D.z || 0 };
});

3. 修正经纬度转换的Z值传递

转回经纬度时,确保LmvVector3使用正确的Z值:

const rotatedPolylineLatLng = rotatedPolyline3D.map((point: any) => {
  const pointLatLng = localCS.current.lmv2LL84Point(
    new (Autodesk.Viewing.Private as any).LmvVector3(point.x, point.y, point.z || 0),
  );
  return { lat: pointLatLng.y, lng: pointLatLng.x };
});

最终修正后的rotatePolyline函数

function rotatePolyline(polyline: any, angle: any) {
  if (!modelOrigin || !polyline) return;

  const polyline3D = polyline.map((point: any) => {
    const point3D = localCS.current.LL842LmvPoint({ x: point.lng, y: point.lat });
    return { x: point3D.x, y: point3D.y, z: point3D.z || 0 };
  });

  const rotatedPolyline3D = polyline3D.map((point: any) =>
    rotatePoint(point, modelOrigin, angle),
  );

  const rotatedPolylineLatLng = rotatedPolyline3D.map((point: any) => {
    const pointLatLng = localCS.current.lmv2LL84Point(
      new (Autodesk.Viewing.Private as any).LmvVector3(point.x, point.y, point.z),
    );
    return { lat: pointLatLng.y, lng: pointLatLng.x };
  });

  return rotatedPolylineLatLng;
}

完成以上修正后,Polyline会和Polygon保持一致的旋转行为,不会出现偏移。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 12:15:25