- border polygon src\js\layer\TinLayer.ts

This commit is contained in:
Arno Kaimbacher 2021-06-25 16:19:15 +02:00
parent 7e92499556
commit 4504b82429
4 changed files with 651 additions and 594 deletions

974
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,7 @@
https://jsfiddle.net/prisoner849/8uxw667m/ https://jsfiddle.net/prisoner849/8uxw667m/
https://stackoverflow.com/questions/42348495/three-js-find-all-points-where-a-mesh-intersects-a-plane https://stackoverflow.com/questions/42348495/three-js-find-all-points-where-a-mesh-intersects-a-plane
https://discourse.threejs.org/t/get-edges-between-vertices-outer-polygon/10213/8
https://jsfiddle.net/prisoner849/uqm6bk1k/

View File

@ -29,11 +29,40 @@ import { LineSegments } from 'three/src/objects/LineSegments';
import { PointsMaterial } from 'three/src/materials/PointsMaterial'; import { PointsMaterial } from 'three/src/materials/PointsMaterial';
import { Points } from 'three/src/objects/Points'; import { Points } from 'three/src/objects/Points';
import { Line } from 'three/src/objects/Line'; import { Line } from 'three/src/objects/Line';
import { ConvexGeometry } from 'three/examples/jsm/geometries/ConvexGeometry'; // import hull from 'hull.js/src/hull';
// import concaveman from 'concaveman/index';
const POINTURL = 'https://geusegdi01.geus.dk/geom3d/data/nodes/'; const POINTURL = 'https://geusegdi01.geus.dk/geom3d/data/nodes/';
const EDGEURL = 'https://geusegdi01.geus.dk/geom3d/data/triangles/'; const EDGEURL = 'https://geusegdi01.geus.dk/geom3d/data/triangles/';
export class Point3 extends Vector3 {
// public x: number;
// public y: number;
private values: number[];
public checked: boolean;
public faceIndex: number;
constructor(x?: number, y?: number, z?: number) {
super(x, y, z);
// this.x = x;
// this.y = y;
// this.z = z;
}
public equals(v, tolerance?): boolean {
if (tolerance === undefined) {
return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));
} else {
return ((Math.abs(v.x - this.x) < tolerance) && (Math.abs(v.y - this.y) < tolerance) && (Math.abs(v.z - this.z) < tolerance));
}
}
public toString(): string {
return "x=" + this.x + " y=" + this.y;
}
}
class TinLayer extends Layer { class TinLayer extends Layer {
name: string; name: string;
@ -42,6 +71,7 @@ class TinLayer extends Layer {
borderVisible; borderVisible;
scale; scale;
objectGroup; objectGroup;
borderGroup;
visible: boolean; visible: boolean;
opacity: number; opacity: number;
materialParameter: Array<string>; materialParameter: Array<string>;
@ -92,6 +122,8 @@ class TinLayer extends Layer {
frontStencil: Scene; frontStencil: Scene;
backStencil: Scene; backStencil: Scene;
capsScene: Scene; capsScene: Scene;
p_vertices: Array<Point3>;
tolerance : number = 0.001;
constructor(params) { constructor(params) {
super(); super();
@ -110,12 +142,15 @@ class TinLayer extends Layer {
this.objectGroup = new Group(); this.objectGroup = new Group();
this.q = true; this.q = true;
this.uniforms = uniforms; this.uniforms = uniforms;
this.borderGroup = new Group();
} }
buildBorder(vertices) { buildBorder(vertices) {
let box = this.box = new UpdatableBoxGeometry(vertices); let box = this.box = new UpdatableBoxGeometry(vertices);
this.getScene().add(this.borderGroup);
// this.boxMesh = new Mesh(box, material.capMaterial); // this.boxMesh = new Mesh(box, material.capMaterial);
@ -162,28 +197,34 @@ class TinLayer extends Layer {
var points = new Points(pointsOfIntersection, pointsMaterial); var points = new Points(pointsOfIntersection, pointsMaterial);
this._addObject(points, false); this._addObject(points, false);
// let color = parseInt(this.color, 16);
// var mesh = new Mesh(
// pointsOfIntersection, // re-use the existing geometry
// new MeshBasicMaterial({ color: 0xa9a9a9, side: DoubleSide })
// );
// this._addObject(mesh, false);
// var lines = new LineSegments(pointsOfIntersection, new LineBasicMaterial({ // var lines = new LineSegments(pointsOfIntersection, new LineBasicMaterial({
// color: 0xa9a9a9 // color: 0xa9a9a9
// })); // }));
// material // // var material = new LineBasicMaterial( { color: 0xffffff, linewidth: 1 } );
// var material = new LineBasicMaterial( { color: 0xffffff, linewidth: 1 } ); // // // line
// // line // // var line = new Line( pointsOfIntersection, material );
// var line = new Line( pointsOfIntersection, material ); // this._addObject(lines, false);
// this._addObject(line, false);
// let meshMaterial = new MeshBasicMaterial({
let meshMaterial = new MeshBasicMaterial({ // color: 0xa9a9a9
color: 0xa9a9a9 // });
}); // let convexGeometry;// = new ConvexGeometry( p_vertices );
let convexGeometry;// = new ConvexGeometry( p_vertices ); // const mesh1 = new Mesh( convexGeometry, meshMaterial );
const mesh1 = new Mesh( convexGeometry, meshMaterial ); // this._addObject(mesh1, false);
this._addObject(mesh1, false);
// let meshMaterial = new MeshBasicMaterial({ // let meshMaterial = new MeshBasicMaterial({
// color: 0xa9a9a9 // color: 0xa9a9a9
// }); // });
// let mesh = new Mesh(pointsOfIntersection, meshMaterial); // let mesh = new Mesh(pointsOfIntersection, meshMaterial);
// this._addObject(mesh, false); // this._addObject(mesh, false);
let a = new Vector3(), let a = new Vector3(),
b = new Vector3(), b = new Vector3(),
c = new Vector3(); c = new Vector3();
@ -193,14 +234,17 @@ class TinLayer extends Layer {
let lineAB = new Line3(), let lineAB = new Line3(),
lineBC = new Line3(), lineBC = new Line3(),
lineCA = new Line3(); lineCA = new Line3();
let pointOfIntersection = new Vector3(); // let pointOfIntersection = new Vector3();
box.addEventListener("update", (event) => { box.addEventListener("update", (event) => {
let ar = new Array(this.box.vertices[0], this.box.vertices[1], this.box.vertices[2], this.box.vertices[3]); let ar = new Array(this.box.vertices[0], this.box.vertices[1], this.box.vertices[2], this.box.vertices[3]);
this.planeGeom.setFromPoints(ar); this.planeGeom.setFromPoints(ar);
this.planeGeom.update(); this.planeGeom.update();
p_vertices = []; this.borderGroup.clear();
this.p_vertices = [];
vertices = [];
let mathPlane = new Plane(); let mathPlane = new Plane();
plane.localToWorld(planePointA.copy(plane.geometry.vertices[0])); plane.localToWorld(planePointA.copy(plane.geometry.vertices[0]));
@ -208,12 +252,7 @@ class TinLayer extends Layer {
plane.localToWorld(planePointC.copy(plane.geometry.vertices[2])); plane.localToWorld(planePointC.copy(plane.geometry.vertices[2]));
mathPlane.setFromCoplanarPoints(planePointA, planePointB, planePointC); mathPlane.setFromCoplanarPoints(planePointA, planePointB, planePointC);
const setPointOfIntersection = (line: Line3, plane: Plane) => {
plane.intersectLine(line, pointOfIntersection);
if (pointOfIntersection.x != 0 && pointOfIntersection.y != 0 && pointOfIntersection.z != 0) {
p_vertices.push(pointOfIntersection.clone());
}
}
let geom = this.mainMesh.geometry; let geom = this.mainMesh.geometry;
// this.mainMesh.geometry.faces.forEach(function (face) { // this.mainMesh.geometry.faces.forEach(function (face) {
for (let vi = 0; vi < geom.index.array.length; vi += 3) { for (let vi = 0; vi < geom.index.array.length; vi += 3) {
@ -244,19 +283,45 @@ class TinLayer extends Layer {
lineAB = new Line3(a, b); lineAB = new Line3(a, b);
lineBC = new Line3(b, c); lineBC = new Line3(b, c);
lineCA = new Line3(c, a); lineCA = new Line3(c, a);
setPointOfIntersection(lineAB, mathPlane); this.setPointOfIntersection(lineAB, mathPlane, vi);
setPointOfIntersection(lineBC, mathPlane); this.setPointOfIntersection(lineBC, mathPlane, vi);
setPointOfIntersection(lineCA, mathPlane); this.setPointOfIntersection(lineCA, mathPlane, vi);
} }
if (p_vertices.length > 0) { if (this.p_vertices.length > 0) {
pointsOfIntersection.setFromPoints(p_vertices); // pointsOfIntersection.setFromPoints(p_vertices);
// pointsOfIntersection.computeBoundingSphere()
// pointsOfIntersection.attributes.position.needsUpdate = true;
// // convexGeometry.setFromPoints(p_vertices);
// convexGeometry = new ConvexGeometry( p_vertices );
// convexGeometry.computeBoundingSphere()
// convexGeometry.attributes.position.needsUpdate = true;
let test = this.p_vertices.map(v => {
return [v.x, v.y, v.z];
});
// const indexHull = hull(test, 1); // returns points of the hull (in clockwise order)
// let vertices = indexHull.map(a => {
// return new Vector3(a[0], a[1], a[2]);
// });
// const indexAlpha = concaveman(test, 1);
// let vertices = indexAlpha.map(a => {
// return new Vector3(a[0], a[1], a[2]);
// });
pointsOfIntersection.setFromPoints(this.p_vertices);
pointsOfIntersection.computeBoundingSphere() pointsOfIntersection.computeBoundingSphere()
pointsOfIntersection.attributes.position.needsUpdate = true; pointsOfIntersection.attributes.position.needsUpdate = true;
// convexGeometry.setFromPoints(p_vertices); let contours = this.getContours(this.p_vertices, [], true);
convexGeometry = new ConvexGeometry( p_vertices ); contours.forEach(cntr => {
convexGeometry.computeBoundingSphere() let cntrGeom = new BufferGeometry();
convexGeometry.attributes.position.needsUpdate = true; cntrGeom.setFromPoints(cntr);
let contour = new Line(cntrGeom, new LineBasicMaterial({
color: Math.random() * 0xffffff //0x777777 + 0x777777
}));
this.borderGroup.add(contour);
});
} }
@ -264,7 +329,7 @@ class TinLayer extends Layer {
}); });
// let myPlane = new Plane(new Vector3(0, 1, 0), 0);
// this.frontStencil = new Scene(); // this.frontStencil = new Scene();
// let frontMesh = new Mesh(this.geometry.clone(), material.frontStencilMaterial); // let frontMesh = new Mesh(this.geometry.clone(), material.frontStencilMaterial);
@ -280,6 +345,92 @@ class TinLayer extends Layer {
// this.capsScene.add(this.borderMesh); // this.capsScene.add(this.borderMesh);
} }
private setPointOfIntersection(line: Line3, plane: Plane, faceIndex: number): void {
let pointOfIntersection = new Point3();
plane.intersectLine(line, pointOfIntersection);
if (pointOfIntersection.x != 0 && pointOfIntersection.y != 0 && pointOfIntersection.z != 0) {
// let p = pointOfIntersection.clone();
pointOfIntersection.checked = false;
pointOfIntersection.faceIndex = faceIndex;
this.p_vertices.push(pointOfIntersection);
}
}
private getContours(points: Array<Point3>, contours: Array<any>, firstRun: boolean) {
// console.log("firstRun:", firstRun);
let contour = new Array<Point3>();
// find first line for the contour
let firstPointIndex = 0;
let secondPointIndex = 0;
let firstPoint, secondPoint;
for (let i = 0; i < points.length; i++) {
let point = points[i];
if (point.checked == true) continue;
firstPointIndex = i;
firstPoint = points[firstPointIndex];
firstPoint.checked = true;
secondPointIndex = this.getPairIndex(firstPoint, firstPointIndex, points);
secondPoint = points[secondPointIndex];
secondPoint.checked = true;
contour.push(firstPoint);
contour.push(secondPoint);
break;
}
contour = this.getContour(secondPoint, points, contour);
contours.push(contour);
let allChecked = 0;
points.forEach(p => { allChecked += p.checked == true ? 1 : 0; });
// console.log("allChecked: ", allChecked == points.length);
if (allChecked != points.length) { return this.getContours(points, contours, false); }
return contours;
}
private getPairIndex(point, pointIndex, points) {
let index = 0;
for (let i = 0; i < points.length; i++) {
let p = points[i];
if (i != pointIndex && p.checked == false && p.faceIndex == point.faceIndex) {
index = i;
break;
}
}
return index;
}
private getContour(currentPoint: Point3, points, contour) {
let p1Index = this.getNearestPointIndex(currentPoint, points);
let p1 = points[p1Index];
p1.checked = true;
let p2Index = this.getPairIndex(p1, p1Index, points);
let p2 = points[p2Index];
p2.checked = true;
let isClosed = p2.equals(contour[0], this.tolerance);
if (!isClosed) {
contour.push(p2);
return this.getContour(p2, points, contour);
} else {
contour.push(contour[0]);
return contour;
}
}
private getNearestPointIndex(point, points){
let index = 0;
for (let i = 0; i < points.length; i++){
// let p = points[i];
if (points[i].checked == false && points[i].equals(point, this.tolerance)){
index = i;
break;
}
}
return index;
}
// animate() { // animate() {
// let gl = this._map.renderer.getContext(); // let gl = this._map.renderer.getContext();

View File

@ -383,35 +383,35 @@ class Application {
// The HTML5 Canvas's 'webgl' context obtained from the canvas where the renderer will draw. // The HTML5 Canvas's 'webgl' context obtained from the canvas where the renderer will draw.
let gl = this.renderer.getContext(); let gl = this.renderer.getContext();
if (this.showCaps && gl != undefined) { // if (this.showCaps && gl != undefined) {
// enable stencil test // // enable stencil test
gl.enable(gl.STENCIL_TEST); // gl.enable(gl.STENCIL_TEST);
// for (let i in this.map.layers) { // // for (let i in this.map.layers) {
// let layer = this.map.layers[i]; // // let layer = this.map.layers[i];
// if (layer instanceof TinLayer && layer.name != "Topography") { // // if (layer instanceof TinLayer && layer.name != "Topography") {
// layer.animate(); // // layer.animate();
// break; // // break;
// } // // }
// } // // }
gl.stencilFunc(gl.ALWAYS, 1, 0xff); // gl.stencilFunc(gl.ALWAYS, 1, 0xff);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); // gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
this.renderer.render(this.backStencil, this.map.camera); // this.renderer.render(this.backStencil, this.map.camera);
gl.stencilFunc(gl.ALWAYS, 1, 0xff); // gl.stencilFunc(gl.ALWAYS, 1, 0xff);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); // gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);
this.renderer.render(this.frontStencil, this.map.camera); // this.renderer.render(this.frontStencil, this.map.camera);
gl.stencilFunc(gl.EQUAL, 1, 0xff); // gl.stencilFunc(gl.EQUAL, 1, 0xff);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); // gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
this.renderer.render(this.capsScene, this.map.camera); // this.renderer.render(this.capsScene, this.map.camera);
// disable stencil test // // disable stencil test
gl.disable(gl.STENCIL_TEST); // gl.disable(gl.STENCIL_TEST);
// gl.stencilMask(0); // // gl.stencilMask(0);
// this.renderer.state.setStencilFunc( false ); // // this.renderer.state.setStencilFunc( false );
} // }
this.renderer.render(this.scene, this.map.camera); this.renderer.render(this.scene, this.map.camera);