Creation of walls. Part 1. Creation of equidistant lines

0

To build walls of a given thickness using a given polyline, it is necessary to determine the equidistant lines to this line. The main task of constructing equidistant lines is to find points at the corners of the polyline – the intersections of equidistant lines.

For each point of the polyline, we define the inner and outer points of the equidistant line and add them to the corresponding arrays

for (let i=0; i < points.length; i++){
    if (points[i+1] &amp;&amp; points[i+2]){
        const coner = {};
        coner.pointA = points[i];
        coner.vertex = points[i+1];
        coner.pointC = points[i+2];

        const inside = buildEquidistantPoint(coner, WALLTHICKNESS, 'inner');
        const outer = buildEquidistantPoint(coner, WALLTHICKNESS, 'outer');

        wallArray.push(inside);
        wallArrayOuter.push(outer);
      }
}

The definition of an interior point is as follows

function buildEquidistantPoint(coner, wallThickness, type){
	const halfTickness = 0.5 * wallThickness;
	const leftSide = coner.vertex.clone().sub(coner.pointA.clone()).normalize();
	const rightSide = coner.vertex.clone().sub(coner.pointC.clone()).normalize();
	const angle = rightSide.angle() - leftSide.angle();
	const alfa = angle/2;
	let bisectorLength;
	if(type === 'inner'){
		bisectorLength = halfTickness/Math.sin(-alfa);
	}
	if(type === 'outer'){
		bisectorLength = halfTickness/Math.sin(alfa);
	}
	const bisector = leftSide.clone().rotateAround(new THREE.Vector2(0, 0), alfa);
	const point = coner.vertex.clone().add((bisector.clone()).multiplyScalar(bisectorLength));
	return point;
}

First, we define vectors coplanar to the lines going out from a given point, for this we subtract the vectors of the vertices and normalize them to obtain a unit vector.

const leftSide = coner.vertex.clone().sub(coner.pointA.clone()).normalize();
const rightSide = coner.vertex.clone().sub(coner.pointC.clone()).normalize();

the second – we determine the angle between them

const angle = rightSide.angle() - leftSide.angle();

the equidistant point always lies on the bisector of the angle, so we divide the angle in half

const alfa = angle/2;

then we define the hypotenuse in the triangle formed by half the wall thickness and the polyline. Let’s denote it bisectorLength

bisectorLength = halfTickness/Math.sin(-alfa);

we get a vector going from the vertex to point b by rotating the leftSide vector by the angle alfa

const bisector = leftSide.clone().rotateAround(new THREE.Vector2(0, 0), alfa);

all that remains for us is to move point B along the resulting vector. To do this, multiply it by a scalar – the length of the resulting bisectorLength segment and add the vector of the corner vertex and the resulting vector.

const point = coner.vertex.clone().add((bisector.clone()).multiplyScalar(bisectorLength));

construction of end points of open lines is carried out in a similar way, only the angle is always the same const angle = 3 * Math.PI / 4;

function buildEnding(pointB, pointA, wallThickness) {
	const halfTickness = 0.5 * wallThickness;
	const ending = [];
	const BA = pointB.clone().sub(pointA.clone()).normalize();
	const angle = 3 * Math.PI / 4;
	const bisectorLength = halfTickness/Math.sin(angle);
	const bisectorOuter = BA.clone().rotateAround(new THREE.Vector2(0, 0), -angle);
	const outerEnding = pointB.clone().add((bisectorOuter.clone().negate()).multiplyScalar(bisectorLength));
	ending.push(outerEnding);
	const bisectorInner = BA.clone().rotateAround(new THREE.Vector2(0, 0), angle);
	const innerEnding = pointB.clone().add((bisectorInner.clone().negate()).multiplyScalar(bisectorLength));
	ending.push(innerEnding);
	return ending;
}

The end polyline of points is processed as follows

if(points[0].equals(points[points.length-1])) {
	const coner = {};
	coner.pointA = points[points.length - 2];
	coner.vertex = points[0];
	coner.pointC = points[1];

	const inside = buildEquidistantPoint(coner, WALLTHICKNESS, 'inner');
	const outer = buildEquidistantPoint(coner, WALLTHICKNESS, 'outer');

	wallArray.push(inside);
	wallArrayOuter.push(outer);
	wallArray.push(wallArray[0]);
	wallArrayOuter.push(wallArrayOuter[0]);
} else {
	const end = buildEnding(points[points.length-1], points[points.length-2], WALLTHICKNESS)
	wallArrayOuter.push(...end)
	wallArray.push(wallArrayOuter[wallArrayOuter.length-1]);

	const start = buildEnding(points[0], points[1], WALLTHICKNESS)
	wallArrayOuter.unshift(...start);
	wallArray.unshift(wallArrayOuter[0]);
}

The complete code can be seen here https://jsfiddle.net/Dragon3DGraff/w5pufk04/10/

0