!743 快速构造拉伸实体网格

pull/743/MERGE
ChenX 5 years ago
parent cad71af247
commit 65efa29eff

@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`EdgeGeometry生成 1`] = `432`; exports[`EdgeGeometry生成 1`] = `114`;
exports[`EdgeGeometry生成 2`] = `858`; exports[`EdgeGeometry生成 2`] = `858`;
exports[`EdgeGeometry生成 3`] = `146`; exports[`EdgeGeometry生成 3`] = `60`;
exports[`EdgeGeometry生成2 1`] = `110`; exports[`EdgeGeometry生成2 1`] = `110`;

@ -1,26 +1,188 @@
import { BufferGeometry, Float32BufferAttribute, Matrix4, Mesh, Shape, ShapeUtils, Vector2 } from "three";
import { app } from "../../ApplicationServices/Application"; import { app } from "../../ApplicationServices/Application";
import { TemplateVisualSpace } from "../../DatabaseServices/Template/ProgramTempate/TemplateVisualSpace"; import { Contour } from "../../DatabaseServices/Contour";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Circle } from "../../DatabaseServices/Entity/Circle";
import { Curve } from "../../DatabaseServices/Entity/Curve";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Command } from "../../Editor/CommandMachine"; import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { equaln } from "../../Geometry/GeUtils";
import { HotCMD } from "../../Hot/HotCommand"; import { HotCMD } from "../../Hot/HotCommand";
import { TemplateSplitType } from "../../DatabaseServices/Template/TemplateType"; import { TestDraw } from "../test/TestUtil";
import { SelectTempate } from "../../DatabaseServices/Template/TemplateTest";
import { Entity } from "../../DatabaseServices/Entity/Entity";
@HotCMD @HotCMD
export class Test implements Command export class Test implements Command
{ {
async exec() async exec()
{ {
let enRes = await app.Editor.GetEntity({ Filter: { filterTypes: [Board] } });
if (enRes.Status !== PromptStatus.OK) return;
let br = enRes.Entity as Board;
let t = await SelectTempate(); let ocsInv = br.OCSInv;
if (!t) return; let alMatrix4 = new Matrix4();
let frontHoles: Shape[] = [];
let backHoles: Shape[] = [];
let objs = t.Objects.map(t => t.Object).filter(o => o !== undefined && !o.IsErase) as Entity[]; let frontCurves: Curve[] = [];
let backCurves: Curve[] = [];
for (let o of objs) let frontHoleCurves: Curve[] = [];
let backHoleCurves: Curve[] = [];
for (let g of br.Grooves)
{
let back = false;
let front = false;
if (equaln(g.Thickness, br.Thickness))
{
back = true;
front = true;
}
else
{
if (equaln(g.Position.applyMatrix4(ocsInv).z, 0))
back = true;
else
front = true;
}
alMatrix4.multiplyMatrices(ocsInv, g.OCSNoClone);
let gContour = g.ContourCurve.Clone();
gContour.ApplyMatrix(alMatrix4);
if (gContour instanceof Polyline)
gContour.UpdateMatrixTo(br.ContourCurve.OCS);
let sp: Shape;
if (gContour instanceof Circle)
{
sp = new Shape();
let cen = gContour.Center.applyMatrix4(ocsInv);
sp.ellipse(cen.x, cen.y, gContour.Radius, gContour.Radius, 0, 2 * Math.PI, false, 0);
}
else
sp = gContour.Shape;
gContour.Z0();
gContour.TempData = g.Thickness;
let holeCurves: Curve[] = [];
for (let gg of g.Grooves)
{
let c = gg.ContourCurve;
c.ApplyMatrix(alMatrix4).Z0();
c.TempData = g.Thickness;
holeCurves.push(c);
}
if (back)
{
backHoles.push(sp);
backCurves.push(gContour);
backHoleCurves.push(...holeCurves);
}
if (front)
{
frontHoles.push(sp);
frontCurves.push(gContour);
frontHoleCurves.push(...holeCurves);
}
}
let contourShape = br.ContourCurve.Shape;
let verticesArray: number[] = [];
//draw front
contourShape.holes = frontHoles;
DrawShapeFaces(contourShape, verticesArray, br);
//front 孤岛
let frontCurveContours = frontCurves.map(c => Contour.CreateContour([c]));
DrawIslandFaces(frontHoleCurves, frontCurveContours, verticesArray, br);
//draw back
contourShape.holes = backHoles;
DrawShapeFaces(contourShape, verticesArray, br, false);
let backCurveContours = backCurves.map(c => Contour.CreateContour([c]));
DrawIslandFaces(backHoleCurves, backCurveContours, verticesArray, br, false);
//绘制内部造型
//绘制边缘
//geo
let geo = new BufferGeometry();
geo.setAttribute('position', new Float32BufferAttribute(verticesArray, 3));
TestDraw(new Mesh(geo));
}
}
function DrawIslandFaces(HoleCurves: Curve[], CurveContours: Contour[], verticesArray: number[], br: Board, front = true)
{
for (let c of HoleCurves)
{
let contours = [Contour.CreateContour([c])];
for (let hole of CurveContours)
{
if (!equaln(c.TempData as number, hole.Curve.TempData as number))
{
let newcs: Contour[] = [];
for (let con of contours)
newcs.push(...con.SubstactBoolOperation(hole));
contours = newcs;
}
}
for (let con of contours)
{
DrawShapeFaces(con.Curve.Shape, verticesArray, br);
}
}
}
function DrawShapeFaces(contourShape: Shape, verticesArray: number[], br: Board, front = true)
{
let shapePoints = contourShape.extractPoints(6);
let vertices = shapePoints.shape;
let holes = shapePoints.holes;
let reverse = !ShapeUtils.isClockWise(vertices);
if (reverse)
{
vertices = vertices.reverse();
for (let h = 0, hl = holes.length; h < hl; h++)
{ {
o.ApplyMatrix(o.SpaceOCSInv); let ahole = holes[h];
if (ShapeUtils.isClockWise(ahole))
holes[h] = ahole.reverse();
} }
} }
let faces = ShapeUtils.triangulateShape(vertices, holes);
for (let h of holes)
vertices.push(...h);
for (let f of faces)
{
if (front)
{
newFunction_1(vertices[f[0]]);
newFunction_1(vertices[f[1]]);
newFunction_1(vertices[f[2]]);
}
else
{
newFunction_1(vertices[f[0]]);
newFunction_1(vertices[f[2]]);
newFunction_1(vertices[f[1]]);
}
}
function newFunction_1(v: Vector2)
{
verticesArray.push(v.x);
verticesArray.push(v.y);
if (front)
verticesArray.push(br.Thickness);
else
verticesArray.push(0);
}
} }

@ -11,6 +11,10 @@ import { ObjectId } from './ObjectId';
export abstract class CADObject export abstract class CADObject
{ {
protected _Owner: ObjectId; protected _Owner: ObjectId;
/**
*
*/
public TempData: any;
set Owner(owner: ObjectId) set Owner(owner: ObjectId)
{ {
this._Owner = owner; this._Owner = owner;

@ -131,6 +131,11 @@ export class Entity extends CADObject
return this._Matrix.clone(); return this._Matrix.clone();
} }
get OCSNoClone()
{
return this._Matrix;
}
//直接设置实体的矩阵,谨慎使用该函数,没有更新实体. //直接设置实体的矩阵,谨慎使用该函数,没有更新实体.
set OCS(mat4: Matrix4) set OCS(mat4: Matrix4)
{ {

@ -1,4 +1,4 @@
import { BoxGeometry, BufferGeometry, ExtrudeGeometry, ExtrudeGeometryOptions, Geometry, Line, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Vector3 } from "three"; import { BoxGeometry, BufferGeometry, ExtrudeGeometry, ExtrudeGeometryOptions, Geometry, Line, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Vector3, Path } from "three";
import { arrayClone, arrayLast, arrayRemoveIf, arraySortByNumber, arraySum } from "../../Common/ArrayExt"; import { arrayClone, arrayLast, arrayRemoveIf, arraySortByNumber, arraySum } from "../../Common/ArrayExt";
import { ColorMaterial } from "../../Common/ColorPalette"; import { ColorMaterial } from "../../Common/ColorPalette";
import { equalCurve } from "../../Common/CurveUtils"; import { equalCurve } from "../../Common/CurveUtils";
@ -10,6 +10,7 @@ import { CSG2Geometry, Geometry2CSG } from "../../csg/core/Geometry2CSG";
import { ObjectSnapMode } from "../../Editor/ObjectSnapMode"; import { ObjectSnapMode } from "../../Editor/ObjectSnapMode";
import { boardUVGenerator } from "../../Geometry/BoardUVGenerator"; import { boardUVGenerator } from "../../Geometry/BoardUVGenerator";
import { Box3Ext } from "../../Geometry/Box"; import { Box3Ext } from "../../Geometry/Box";
import { BSPGroupParse } from "../../Geometry/BSPGroupParse";
import { FastWireframe } from "../../Geometry/CreateWireframe"; import { FastWireframe } from "../../Geometry/CreateWireframe";
import { EdgesGeometry } from "../../Geometry/EdgeGeometry"; import { EdgesGeometry } from "../../Geometry/EdgeGeometry";
import { GenerateExtrudeEdgeGeometry } from "../../Geometry/ExtrudeEdgeGeometry"; import { GenerateExtrudeEdgeGeometry } from "../../Geometry/ExtrudeEdgeGeometry";
@ -28,7 +29,6 @@ import { DragPointType } from "./DragPointType";
import { Entity } from "./Entity"; import { Entity } from "./Entity";
import { Polyline } from "./Polyline"; import { Polyline } from "./Polyline";
import { Region } from "./Region"; import { Region } from "./Region";
import { BSPGroupParse } from "../../Geometry/BSPGroupParse";
/** 最大的槽个数,当大于最大个数时,实体不会绘制槽,并且不会校验槽的正确性 */ /** 最大的槽个数,当大于最大个数时,实体不会绘制槽,并且不会校验槽的正确性 */
const MaxGrooveCount = 15; const MaxGrooveCount = 15;
@ -753,15 +753,12 @@ export class ExtrudeSolid extends Entity
* Draw,bsp * Draw,bsp
*/ */
private csg: CSG; private csg: CSG;
private get CSG() get CSG()
{ {
if (this.csg) if (this.csg)
return this.csg; return this.csg;
//实体内保证了就算本实体不绘制也能正确的更新Geo this.csg = Geometry2CSG(this.MeshGeometry);
this.MeshGeometry;
if (!this.csg)
this.csg = Geometry2CSG(this.MeshGeometry as Geometry);
return this.csg; return this.csg;
} }
@ -1231,9 +1228,33 @@ export class ExtrudeSolid extends Entity
if (this._EdgeGeometry) if (this._EdgeGeometry)
return this._EdgeGeometry; return this._EdgeGeometry;
if (this.grooves.length === 0) if (this.grooves.every(g => equaln(g.thickness, this.thickness)))
return GenerateExtrudeEdgeGeometry(this.contourCurve.Shape.getPoints(6).map(AsVector3), this.thickness).applyMatrix4(this.contourCurve.OCS); {
this.MeshGeometry; let pts = [this.ContourCurve.Shape.getPoints(6).map(AsVector3)];
let ocsInv = this.OCSInv;
let alMatrix4 = new Matrix4();
for (let g of this.grooves)
{
alMatrix4.multiplyMatrices(ocsInv, g.OCSNoClone);
let gContour = g.ContourCurve.Clone();
gContour.ApplyMatrix(alMatrix4);
if (gContour instanceof Polyline)
gContour.UpdateMatrixTo(this.contourCurve.OCS);
if (gContour instanceof Circle)
{
let sp = new Path();
let cen = gContour.Center.applyMatrix4(this.contourCurve.OCSInv);
sp.ellipse(cen.x, cen.y, gContour.Radius, gContour.Radius, 0, 2 * Math.PI, false, 0);
pts.push(sp.getPoints(6).map(AsVector3));
}
else
pts.push(gContour.Shape.getPoints(6).map(AsVector3));
}
return GenerateExtrudeEdgeGeometry(pts, this.thickness).applyMatrix4(this.contourCurve.OCSNoClone);
}
this._EdgeGeometry = new EdgesGeometry().FromCSG(this.CSG); this._EdgeGeometry = new EdgesGeometry().FromCSG(this.CSG);
return this._EdgeGeometry; return this._EdgeGeometry;
} }
@ -1241,39 +1262,47 @@ export class ExtrudeSolid extends Entity
private GeneralMeshGeometry() private GeneralMeshGeometry()
{ {
this.csg = undefined; this.csg = undefined;
let grooves = this.Grooves;
let gs: ExtrudeSolid[] = [];//不是全深槽
let contour = this.ContourCurve;
let holes: Contour[] = [];
let geo: Geometry; let ocsInv = this.OCSInv;
if (this.isRect && false) let alMatrix4 = new Matrix4();
for (let g of grooves)
{ {
geo = FastMeshGeometry(this.width, this.height, this.thickness); if (equaln(g.Thickness, this.Thickness))
}
else
{ {
alMatrix4.multiplyMatrices(ocsInv, g.OCSNoClone);
let gContour = g.ContourCurve.Clone();
gContour.ApplyMatrix(alMatrix4);
holes.push(Contour.CreateContour(gContour));
}
else if (g.Thickness > 0)
gs.push(g);
}
let shape = new Shape(Contour.CreateContour(contour), holes);
let extrudeSettings: ExtrudeGeometryOptions = { let extrudeSettings: ExtrudeGeometryOptions = {
steps: 1, steps: 1,
bevelEnabled: false, bevelEnabled: false,
depth: this.thickness, depth: this.Thickness,
UVGenerator: this.UCGenerator, UVGenerator: this.UCGenerator,
}; };
geo = new ExtrudeGeometry(this.ContourCurve.Shape, extrudeSettings); let geo = new ExtrudeGeometry(shape.Shape, extrudeSettings);
geo.applyMatrix4(this.contourCurve.OCS); geo.applyMatrix4(contour.OCSNoClone);
}
this.csg = Geometry2CSG(geo);
if (this.grooves.length === 0 || this.grooves.length > MaxGrooveCount)
{
ScaleUV(geo); ScaleUV(geo);
if (gs.length === 0 || gs.length > MaxGrooveCount)
return geo; return geo;
}
for (let g of this.grooves) this.csg = Geometry2CSG(geo);
{ for (let g of gs)
if (g.thickness > 0) this.csg = this.csg.subtract(g.CSG.transform1(this.OCSInv.multiply(g.OCSNoClone)));
this.csg = this.csg.subtract(g.CSG.transform1(this.OCSInv.multiply(g.OCS)));
}
let bgeo = CSG2Geometry(this.csg); let bgeo = CSG2Geometry(this.csg);
ScaleUV(bgeo);
return bgeo; return bgeo;
} }

@ -3,28 +3,31 @@ import { arrayLast } from "../Common/ArrayExt";
import { equalv3 } from "./GeUtils"; import { equalv3 } from "./GeUtils";
import { FixIndex } from "../Common/Utils"; import { FixIndex } from "../Common/Utils";
export function GenerateExtrudeEdgeGeometry(contourPoints: Vector3[], height: number) export function GenerateExtrudeEdgeGeometry(contourPoints: Vector3[][], height: number)
{
let pts: Vector3[] = [];
for (let cs of contourPoints)
pts.push(...GenerateExtrudeEdgeGeometryPoints(cs, height));
let geo = new BufferGeometry().setFromPoints(pts);
return geo;
}
function GenerateExtrudeEdgeGeometryPoints(contourPoints: Vector3[], height: number)
{ {
if (equalv3(contourPoints[0], arrayLast(contourPoints))) if (equalv3(contourPoints[0], arrayLast(contourPoints)))
contourPoints.pop(); contourPoints.pop();
let pts: Vector3[] = []; let pts: Vector3[] = [];
let hpts = contourPoints.map(p => new Vector3(p.x, p.y, height)); let hpts = contourPoints.map(p => new Vector3(p.x, p.y, height));
let count = contourPoints.length; let count = contourPoints.length;
for (let i = 0; i < count; i++) for (let i = 0; i < count; i++)
{ {
pts.push(contourPoints[i], contourPoints[FixIndex(i + 1, count)], pts.push(contourPoints[i], contourPoints[FixIndex(i + 1, count)], hpts[i], hpts[FixIndex(i + 1, count)], contourPoints[i], hpts[i]);
hpts[i], hpts[FixIndex(i + 1, count)],
contourPoints[i], hpts[i]
);
} }
return pts;
let geo = new BufferGeometry().setFromPoints(pts);
return geo;
} }
export function GenerateBoxEdgeGeometry(length: number, width: number, height: number) export function GenerateBoxEdgeGeometry(length: number, width: number, height: number)
{ {
let pts = [new Vector3(), new Vector3(length), new Vector3(length, width), new Vector3(0, width)]; let pts = [new Vector3(), new Vector3(length), new Vector3(length, width), new Vector3(0, width)];
return GenerateExtrudeEdgeGeometry(pts, height); return GenerateExtrudeEdgeGeometry([pts], height);
} }

@ -1,9 +1,13 @@
import { Matrix4 } from "three"; import { Matrix4, Vector3 } from "three";
import { arrayLast } from "../../Common/ArrayExt";
import { FixIndex } from "../../Common/Utils";
import { equalv3 } from "../../Geometry/GeUtils";
import { CSG } from "./CSG"; import { CSG } from "./CSG";
import { Polygon } from "./math/Polygon3"; import { Polygon } from "./math/Polygon3";
import { Side } from "./math/Side"; import { Side } from "./math/Side";
import { Vector2D } from "./math/Vector2"; import { Vector2D } from "./math/Vector2";
import { Vector3D } from "./math/Vector3"; import { Vector3D } from "./math/Vector3";
import { Vertex2D } from "./math/Vertex2";
import { Vertex3D } from "./math/Vertex3"; import { Vertex3D } from "./math/Vertex3";
import { Tree } from "./trees"; import { Tree } from "./trees";
import { canonicalizeCAG } from "./utils/canonicalize"; import { canonicalizeCAG } from "./utils/canonicalize";
@ -20,6 +24,25 @@ export class CAG
constructor(public sides: Side[] = []) constructor(public sides: Side[] = [])
{ {
} }
fromPoints(pts: Vector3[]): this
{
this.sides.length = 0;
if (equalv3(pts[0], arrayLast(pts)))
pts.pop();
for (let i = 0; i < pts.length; i++)
{
let p1 = pts[i];
let p2 = pts[FixIndex(i + 1, pts)];
let side = new Side(new Vertex2D(new Vector2D(p1.x, p1.y)), new Vertex2D(new Vector2D(p2.x, p2.y)));
this.sides.push(side);
}
return this;
}
flipped() flipped()
{ {
let newsides = this.sides.map(side => side.flipped()); let newsides = this.sides.map(side => side.flipped());
@ -72,7 +95,7 @@ export class CAG
return new CSG(polygons); return new CSG(polygons);
} }
private toPolygons(bottom = false) toPolygons(bottom = false): Polygon[]
{ {
let bounds = this.getBounds(); let bounds = this.getBounds();
bounds[0].sub(new Vector2D(1, 1)); bounds[0].sub(new Vector2D(1, 1));
@ -95,6 +118,12 @@ export class CAG
b.invert(); b.invert();
a.clipTo(b); a.clipTo(b);
return a.allPolygons(); let polys = a.allPolygons();
for (let poly of polys)
{
for (let p of poly.vertices)
p.uv = new Vector2D(p.pos.x, p.pos.y);
}
return polys;
} }
} }

@ -15,6 +15,20 @@ export class Side
new Vertex3D(this.vertex1.pos.toVector3D(z1)), new Vertex3D(this.vertex1.pos.toVector3D(z1)),
new Vertex3D(this.vertex0.pos.toVector3D(z1)) new Vertex3D(this.vertex0.pos.toVector3D(z1))
]; ];
if (this.vertex0.pos.y - this.vertex0.pos.y < 0.01)
{
vertices[0].uv = new Vector2D(z0 - 1, this.vertex0.pos.x);
vertices[1].uv = new Vector2D(z0 - 1, this.vertex1.pos.x);
vertices[2].uv = new Vector2D(z1 - 1, this.vertex0.pos.x);
vertices[3].uv = new Vector2D(z1 - 1, this.vertex1.pos.x);
}
else
{
vertices[0].uv = new Vector2D(z0 - 1, this.vertex0.pos.y);
vertices[1].uv = new Vector2D(z0 - 1, this.vertex1.pos.y);
vertices[2].uv = new Vector2D(z1 - 1, this.vertex0.pos.y);
vertices[3].uv = new Vector2D(z1 - 1, this.vertex1.pos.y);
}
return new Polygon(vertices); return new Polygon(vertices);
} }

Loading…
Cancel
Save