I'm developing an angular app in which i upload svg image to leaflet and place it/scale it/rotate it using (distortable image overlay) .
After that i Draw polygons inside that image as zones.
Those two are working perfectly fine .
The problem is that i have a function that will take that svg image and make it as a plane and then project the coordinates of the drawn polygons inside threejs, I tried everything but the result is always shifted.
Those are the screenshots
This screenshot after drawing polygon in leaflet - tilelayer is hidden here-
This when i try to make it 3d using threejs
This how i display the svg and the plane
private async createFloorFromSvg(svgUrl: string,corners: number[][]): Promise<void> {
const floorTopLeft = new THREE.Vector3(corners[0][0], 0, corners[0][1]);
const floorTopRight = new THREE.Vector3(corners[1][0], 0, corners[1][1]);
const middle= new THREE.Vector3((corners[1][0]+corners[0][0])/2,0,(corners[2][1]+corners[0][1])/2)
const floorBottomLeft = new THREE.Vector3(corners[2][0], 0, corners[2][1]);
const response = await fetch(svgUrl);
const svgContent = await response.text();
const tempSvg = new DOMParser().parseFromString(svgContent, 'image/svg+xml');
const svgWidth = parseFloat(tempSvg.documentElement.getAttribute('width')) // Default width if not specified
const svgHeight = parseFloat(tempSvg.documentElement.getAttribute('height')) // Default height if not specified
const loader = new SVGLoader();
const group = new THREE.Group();
loader.load(svgUrl,function (data) {
const paths = data.paths;
let renderOrder = 0;
for ( const path of data.paths ) {
const fillColor = path.userData.style.fill;
const material = new THREE.MeshBasicMaterial( {
side: THREE.DoubleSide,
depthWrite: false,
} );
const shapes = SVGLoader.createShapes( path );
for ( const shape of shapes ) {
const geometry = new THREE.ShapeGeometry( shape );
const mesh = new THREE.Mesh( geometry, material );
mesh.renderOrder = renderOrder ++;
group.add( mesh );
}
const material2 = new THREE.MeshBasicMaterial( {
transparent: true,
side: THREE.DoubleSide,
depthWrite: false
} );
for ( const subPath of path.subPaths ) {
const geometry = SVGLoader.pointsToStroke( subPath.getPoints(), path.userData.style );
if ( geometry ) {
const mesh = new THREE.Mesh( geometry, material2 );
mesh.renderOrder = renderOrder ++;
group.add( mesh );
}
}
}
const planeGeometry = new THREE.PlaneGeometry(svgWidth, svgHeight, 1, 1);
const planeMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
side: THREE.DoubleSide,
depthWrite: false,
transparent: true,
opacity: 0.5,
depthTest:false
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
group.position.copy(new THREE.Vector3((svgWidth/2),(svgHeight/2),0));
plane.position.copy(new THREE.Vector3((svgWidth/2),(svgHeight/2),0));
group.rotation.z = Math.PI ;
group.add(plane);
});
this.scene.add(group);
}
This how i try to display the polygons
private convertPolygonToImageCoordinates(polygonCoordinates: number[][], svgCorners: number[][], svgWidth: any, svgHeight: any): THREE.Vector3[] {
const localCoordinates: THREE.Vector3[] = [];
this.calculateRotationAngle(svgCorners)
const svgTopLeft = new THREE.Vector3(svgCorners[0][0], 0, svgCorners[0][1]);
const svgTopRight = new THREE.Vector3(svgCorners[1][0], 0, svgCorners[1][1]);
const svgBottomLeft = new THREE.Vector3(svgCorners[2][0], 0, svgCorners[2][1]);
const svgBottomRight = new THREE.Vector3(svgCorners[3][0], 0, svgCorners[3][1]);
const scaleX = svgBottomLeft.distanceTo(svgBottomRight) / svgWidth;
const scaleZ = svgTopLeft.distanceTo(svgBottomLeft) / svgHeight;
const transformationMatrix = new THREE.Matrix4();
transformationMatrix.scale(new THREE.Vector3(scaleX, 1, scaleZ));
const translateX = (svgTopLeft.x ) ;
const translateY = 0;
const translateZ = (svgTopLeft.z ) ;
const directionVector = svgTopLeft.clone().sub(svgTopRight);
const rotationAngle = Math.atan2(directionVector.z, directionVector.x);
for (const [longitude, latitude] of polygonCoordinates) {
const x = (longitude - translateX) / scaleX;
console.log('longitude - translateX/s',x)
const y = translateY;
const z = (latitude - translateZ) / scaleZ;
console.log('latitude - translateZ/s',z)
localCoordinates.push(new THREE.Vector3(x, y, z));
}
const rotationMatrix = new THREE.Matrix4().makeRotationY(rotationAngle);
localCoordinates.forEach(point => {
point.applyMatrix4(rotationMatrix);
});
this.createPolygon(localCoordinates,svgWidth,svgHeight);
return localCoordinates;
}
private createPolygon(coordinates: THREE.Vector3[],svgWidth: number,svgHeight: number): void {
const shapePoints = coordinates.map(coord => new THREE.Vector2(coord.x, coord.z));
const shape = new THREE.Shape(shapePoints);
const extrudeSettings = {
depth: 50,
bevelEnabled: false,
};
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings );
const material =new THREE.MeshStandardMaterial({
color: 0x778899,
roughness: 0
})
const polygon = new THREE.Mesh(geometry, material);
var position = new THREE.Vector3();
polygon.getWorldPosition( position );
this.camera.lookAt( position );
polygon.position.copy(new THREE.Vector3((svgWidth/2),(svgHeight/2),0));
this.scene.add(polygon);
}
I want to fix those misplaced polygons