Rotate the google map polyline around the certain point

230 Views Asked by At

I am working with a 3D model using Autodesk Forge extension Geolocation and displaying it on Google Map (@react-google-maps/api). I have the coordinates of a polygon in 3D world coordinates and a polyline in latitude and longitude coordinates. I also have the modelOrigin, which is the center point of the 3D model. I am trying to rotate the polyline around the modelOrigin, as the same way I am rotating the polygon. The polygon itself rotates fine but the problem is with rotating polyline. I am noticing that the rotation distance for the polyline is too long and the polyline is moving away from the modelOrigin as soon as I try to rotate it.

I am using the LL842LmvPoint method of Autodesk Forge Geolocation extension to convert the polyline's latitude and longitude coordinates (lat and lng) into 3D world coordinates and lmv2LL84Point method to convert back to lat lng.

This is how I get my polygon (buildingProfile) coordinates and 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]);

As soon as I set initialBuildingProfile there is an useEffect that triggers another function which is responsible converting buildingProfile from 3d word coords into lat and lng coords

  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);
  }

And the rendering looks something like this:

<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>;

Result:

enter image description here

Now rotation part,

  // 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,
  };
}

And rotation for polyline(red line on y axis)

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;
  }

Finally, when user clicks on rotate right button I do this:

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

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

After rotating by 15 degrees, my polygon looks fine but polyline gets far away from my modelOrigin.

enter image description here

enter image description here

Expected result:

enter image description here

0

There are 0 best solutions below