@xtor/cga.js
Version:
Xtor Compute Geometry Algorithm Libary 计算几何算法库
312 lines (280 loc) • 12.8 kB
JavaScript
import "./app.css"
import * as cga from "./";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
import { Point } from "./struct/3d/Point";
import { BufferGeometry, Geometry, Line, LineDashedMaterial, Float32BufferAttribute, PointsMaterial, Points, LineBasicMaterial, Mesh, WebGLRenderer, PerspectiveCamera, Scene, HemisphereLight, PolarGridHelper, Face3, DoubleSide, CylinderBufferGeometry, MeshStandardMaterial, MeshBasicMaterial, AxesHelper, SphereBufferGeometry } from "three";
import { Quaternion } from "./math/Quaternion";
import { v3, Vector3 } from "./math/Vector3";
import { Polyline } from "./struct/3d/Polyline";
import { ConvexHull } from "./alg/convexHull";
import { verctorToNumbers } from "./alg/points";
import { extrudeToMesh } from "./render/threeaid";
function toDisSeg(obj, opts) {
var geometry = new Geometry()
geometry.vertices.push(...obj)
var material = new LineDashedMaterial({
color: 0xff0000,
dashSize: 1,
gapSize: 1,
scale: 1, // 比例越大,虚线越密;反之,虚线越疏
...opts
});
//
// Line.computeLineDistances(geometry);//
var line = new Line(geometry, material);
line.computeLineDistances();
return line;
}
function toPoints(points) {
var geometry = new BufferGeometry()
var v3ary = verctorToNumbers(points);
geometry.setAttribute('position', new Float32BufferAttribute(v3ary, 3));
var material = new PointsMaterial({ size: 5, sizeAttenuation: false, color: 0x0ff0f0, alphaTest: 0.9, transparent: true });
return new Points(geometry, material);
}
function toPolygon(points) {
var geometry = new Geometry()
geometry.vertices.push(...points);
geometry.vertices.push(points[0]);
var material = new LineBasicMaterial({ color: 0xff8fff });
return new Line(geometry, material);
}
function toMesh(obj, opts) {
var renderObj = null;
if (obj instanceof cga.Point || obj.isVector3)
{
var geometry = new BufferGeometry()
geometry.setAttribute('position', new Float32BufferAttribute([obj.x, obj.y, obj.z], 3));
var material = new PointsMaterial({ size: 5, sizeAttenuation: false, color: 0x0ff0f0, alphaTest: 0.9, transparent: true });
renderObj = new Points(geometry, material);
} else if (obj instanceof cga.Line)
{
var geometry = new Geometry()
var v1 = obj.direction.clone().multiplyScalar(10000).add(obj.origin);
var v2 = obj.direction.clone().multiplyScalar(-10000).add(obj.origin);
geometry.vertices.push(v1, v2);
var material = new LineBasicMaterial({ color: 0xffff8f });
renderObj = new Line(geometry, material);
} else if (obj instanceof cga.Ray)
{
var geometry = new Geometry()
var v1 = obj.direction.clone().multiplyScalar(10000).add(obj.origin);
geometry.vertices.push(obj.origin, v1);
var material = new LineBasicMaterial({ color: 0xff8fff });
renderObj = new Line(geometry, material);
} else if (obj instanceof cga.Segment)
{
var geometry = new Geometry()
geometry.vertices.push(obj.p0, obj.p1);
var material = new LineBasicMaterial({ color: 0x8fffff });
renderObj = new Line(geometry, material);
} else if (obj instanceof cga.Triangle)
{
var geometry = new Geometry()
geometry.vertices = [...obj];
geometry.faces.push(new Face3(0, 1, 2))
var material = new MeshBasicMaterial({ color: 0x8f8fff, side: DoubleSide });
renderObj = new Mesh(geometry, material);
}
else if (obj instanceof cga.Polyline)
{
var geometry = new Geometry()
geometry.vertices.push(...obj);
var material = new LineBasicMaterial({ color: 0xff8fff });
renderObj = new Line(geometry, material);
} else if (obj instanceof cga.Polygon)
{
}
return renderObj;
}
function randomV3() {
return cga.v3(Math.random() * 100 - 50, Math.random() * 100, Math.random() * 100 - 50);
}
function randomP() {
return cga.Point(Math.random() * 100 - 50, Math.random() * 100, Math.random() * 100 - 50);
}
const container = document.body;
var infoPanel = document.createElement("div");
infoPanel.classList.add("info_panel");
document.body.append(infoPanel)
const renderer = new WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff);
const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
camera.position.set(0, 160, -120);
const control = new OrbitControls(camera, renderer.domElement);
container.append(renderer.domElement);
window.addEventListener("resize", () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
camera.updateMatrix();
})
var scene = new Scene();
scene.add(new HemisphereLight(0xffffff, 0x555555));
// scene.add(new gl.Mesh(new gl.SphereBufferGeometry(1, 30, 30), new gl.MeshStandardMaterial()))
// scene.add(toMesh(new Point(10, 0, 0)))
// scene.add(new PolarGridHelper(100, 8, 10, 64, 0x0a9ff0, 0x0af09f))
scene.add(new AxesHelper(10000))
//---点与直线的距离测试----------------------------------------------------------------
// var point = new cga.Point().copy(randomV3());
// var line = new cga.Line(randomV3(), randomV3());
// var result = point.distanceLine(line);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(point));
// scene.add(toMesh(line));
// scene.add(toDisSeg([point, result.lineClosest]))
//---点与射线的距离测试----------------------------------------------------------------
// var point = new cga.Point().copy(randomV3());
// var ray = new cga.Ray(randomV3(), randomV3().normalize());
// var result = point.distanceRay(ray);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(point));
// scene.add(toMesh(ray));
// scene.add(toDisSeg([point, result.rayClosest]))
// scene.add(toMesh(ray));
//---点与线段的距离测试----------------------------------------------------------------
// var point = new cga.Point().copy(randomV3());
// var seg = new cga.Segment(randomV3(), randomV3());
// var result = point.distanceSegment(seg);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(point));
// scene.add(toMesh(seg));
// scene.add(toDisSeg([point, result.segmentClosest])
//---点与折线的距离测试----------------------------------------------------
// var vs = [];
// for (let i = 0; i < 100000; i++)
// {
// vs.push(randomV3());
// }
// var point = new cga.Point().copy(randomV3());
// var polyline = new cga.Polyline(vs);
// console.time("测试法")
// var result = point.distancePolyLine(polyline);
// console.timeEnd("测试法")
// console.time("线性检索")
// var result1 = point.distancePolyLine1(polyline);
// console.timeEnd("线性检索")
// infoPanel.innerText = JSON.stringify(result) + "\n" + JSON.stringify(result1);
// scene.add(toMesh(point));
// scene.add(toMesh(polyline));
// scene.add(toDisSeg([point, result.segmentClosest]))
// scene.add(toDisSeg([point, result1.segmentClosest], { color: 0x00ff00 }))
//---点与三角形的距离测试----------------------------------------------------------------
// var point = new cga.Point().copy(randomV3());
// var triangle = new cga.Triangle(randomV3(), randomV3(), randomV3());
// var result = point.distanceTriangle(triangle);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(point));
// scene.add(toMesh(triangle));
// scene.add(toMesh(result.closest));
// scene.add(toDisSeg([point, result.closest]))
//---直线与直线的距离测试----------------------------------------------------------------
// var line = new cga.Line(randomV3(), randomV3());
// var line1 = new cga.Line(randomV3(), randomV3());
// var result = line.distanceLine(line1);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(line));
// scene.add(toMesh(line1));
// scene.add(toMesh(result.closestPoint[0]));
// scene.add(toMesh(result.closestPoint[1]));
// scene.add(toDisSeg(result.closestPoint))
//---直线与射线的距离测试----------------------------------------------------------------
// var line = new cga.Line(randomV3(), randomV3());
// var ray = new cga.Ray(randomV3(), randomV3().normalize());
// var result = line.distanceRay(ray);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(line));
// scene.add(toMesh(ray));
// scene.add(toMesh(result.closestPoint[0]));
// scene.add(toMesh(result.closestPoint[1]));
// scene.add(toDisSeg(result.closestPoint))
//---直线与射线的距离测试----------------------------------------------------------------
// var ray0 = new cga.Ray(randomV3(), randomV3().normalize());
// var ray1 = new cga.Ray(randomV3(), randomV3().normalize());
// var result = ray0.distanceRay(ray1);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(ray0));
// scene.add(toMesh(ray1));
// scene.add(toMesh(result.closestPoint[0]));
// scene.add(toMesh(result.closestPoint[1]));
// scene.add(toDisSeg(result.closestPoint))
//---直线与射线的距离测试----------------------------------------------------------------
// var ray = new cga.Ray(randomV3(), randomV3().normalize());
// var segment = new cga.Segment(randomV3(), randomV3());
// var result = ray.distanceSegment(segment);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(ray));
// scene.add(toMesh(segment));
//
// scene.add(toMesh(result.closests[0]));
// scene.add(toMesh(result.closests[1]));
// scene.add(toDisSeg(result.closests))
//---线段与线段的距离测试----------------------------------------------------------------
// var seg0 = new cga.Segment(randomV3(), randomV3());
// var seg1 = new cga.Segment(randomV3(), randomV3());
// var result = seg0.distanceSegment(seg1);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(seg0));
// scene.add(toMesh(seg1));
// scene.add(toMesh(result.closest[0]));
// scene.add(toMesh(result.closest[1]));
// scene.add(toDisSeg(result.closest))
//---折线偏移测试----------------------------------------------------------------
// var polyline = new Polyline([v3(0, 0, 0), v3(0, 0, 10), v3(2, 0, 20), v3(5, 0, 30), v3(10, 0, 40), v3(17, 0, 50)])
// scene.add(toMesh(polyline));
//
// polyline.offset(2);
// var result = seg0.distanceSegment(seg1);
// infoPanel.innerText = JSON.stringify(result);
// scene.add(toMesh(seg0));
// scene.add(toMesh(seg1));
// scene.add(toMesh(result.closest[0]));
// scene.add(toMesh(result.closest[1]));
// scene.add(toDisSeg(result.closest))
// scene.add(new gl.GridHelper(60, 30))
// scene.add(new gl.AxesHelper(1000))
// scene.add(toMesh(new cga.Line(new cga.Point(0, 10, 0), new cga.Point(3, 10, 20))))
// scene.add(toMesh(new cga.Segment(new cga.Point(10, 10, 0), new cga.Point(3, 0, 20))))
// scene.add(toMesh(new cga.Ray(new cga.Point(0, 10, 0), new cga.v3(1, 1, 1))))
// scene.add(toMesh(new cga.Polyline([new cga.Point(0, 0, 0),
// new cga.v3(1, 0, 1),
// new cga.v3(2, 0, 1),
// new cga.v3(2, 0, 2),
// new cga.v3(3, 0, 2),
// ])))
// scene.add(toMesh(new cga.Triangle(new cga.Point(-1, 0, -1),
// new cga.v3(-1, 0, -4),
// new cga.v3(-4, 0, -1)
// )))
// var mesh = new Mesh(new SphereBufferGeometry(10,3,3), new MeshBasicMaterial({color:0xff8880, wireframe: true }));
// mesh.position.y = 10;
// mesh.position.x = -25;
// scene.add(mesh);
// var mesh = new Mesh(new SphereBufferGeometry(10,10,10), new MeshBasicMaterial({color:0xff8888, wireframe: true }));
// mesh.position.y = 10;
// scene.add(mesh);
// var mesh = new Mesh(new SphereBufferGeometry(10,20,20), new MeshBasicMaterial({color:0xff8088, wireframe: true }));
// mesh.position.y = 10;
// mesh.position.x = 25;
// scene.add(mesh);
var points = [];
for (let i = 0; i < 100; i++)
{
const point = new Point(Math.random() * 100 - 50, Math.random() * 100 - 50, 0);
points.push(point);
}
var convexHull = new ConvexHull(points, { planeNormal: cga.Vector3.UnitZ });
var hull = convexHull.hull;
scene.add(toPoints(points));
scene.add(toPolygon(hull));
var mesh = extrudeToMesh([v3(-5, 0, 0), v3(5, 0)], [v3(0, 0, 0), v3(0, 0, 100), v3(100, 0, 200)], { normal: Vector3.UnitZ })
scene.add(mesh);
function render() {
renderer.render(scene, camera)
}
function animate(params) {
render()
requestAnimationFrame(animate)
}
animate();