From ed9e0432e115352e4382cf76a7bc13a76a2291e0 Mon Sep 17 00:00:00 2001 From: XCAD Date: Tue, 6 Feb 2018 14:56:43 +0800 Subject: [PATCH] =?UTF-8?q?!10=20=E5=AE=9E=E7=8E=B0=E9=9D=A2=E5=9F=9F?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E5=92=8C=E9=9D=A2=E5=9F=9F=E5=AE=9E=E4=BD=93?= =?UTF-8?q?.=20Merge=20pull=20request=20!10=20from=20XCAD/region?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __test__/ALG/region.test.ts | 2 +- src/Add-on/DrawRegion.ts | 88 +++++------ src/Add-on/DrawTestReg.ts | 34 ++-- src/Add-on/RevPl.ts | 23 +++ src/ApplicationServices/mesh/createBoard.ts | 4 +- src/DatabaseServices/Arc.ts | 20 ++- src/DatabaseServices/Ellipse.ts | 13 +- src/DatabaseServices/Polyline.ts | 63 +++++++- src/DatabaseServices/Region.ts | 163 +++++++++++++------- src/Editor/CommandRegister.ts | 6 + src/Geometry/RegionParse.ts | 14 +- 11 files changed, 300 insertions(+), 130 deletions(-) create mode 100644 src/Add-on/RevPl.ts diff --git a/__test__/ALG/region.test.ts b/__test__/ALG/region.test.ts index 460ec2b45..7a46085ee 100644 --- a/__test__/ALG/region.test.ts +++ b/__test__/ALG/region.test.ts @@ -1,7 +1,7 @@ import { Vector3 } from 'three'; import { Line } from './../../src/DatabaseServices/Line'; -import { RegionParse } from '../../src/Geometry/RegionParse'; +import { RegionParse } from './../../src/Geometry/RegionParse'; function expectReg(alg: RegionParse) { diff --git a/src/Add-on/DrawRegion.ts b/src/Add-on/DrawRegion.ts index e81529727..d2496f4c2 100644 --- a/src/Add-on/DrawRegion.ts +++ b/src/Add-on/DrawRegion.ts @@ -1,63 +1,59 @@ -import { app } from '../ApplicationServices/Application'; -import { Curve } from '../DatabaseServices/Curve'; -import { Region } from '../DatabaseServices/Region'; -import { Command } from '../Editor/CommandMachine'; -import { SelectSet } from '../Editor/SelectSet'; -import { Vector3 } from 'three'; -import { RegionParse } from '../Geometry/RegionParse'; +import { Command } from "../Editor/CommandMachine"; +import { Region } from "../DatabaseServices/Region"; +import { app } from "../ApplicationServices/Application"; +import { Vector3 } from "three"; +import { Line } from "../DatabaseServices/Line"; +import { Curve } from "../DatabaseServices/Curve"; +import { CreateRegion } from "../Geometry/RegionAlg"; +import { SelectSet } from "../Editor/SelectSet"; +import { Circle } from "../DatabaseServices/Circle"; +import { Ellipse } from "../DatabaseServices/Ellipse"; +import { Polyline } from "../DatabaseServices/Polyline"; +import { Arc } from "../DatabaseServices/Arc"; +import { RegionParse, Route } from '../Geometry/RegionParse'; export class DrawRegion implements Command { async exec(ss: SelectSet) { - let cus: Curve[] = []; - for (let o of ss.SelectObjectList) + let lines: Curve[] = []; + + for (let en of ss.SelectEntityList) { - if (o.userData && o.userData instanceof Curve) + if (en instanceof Circle || en instanceof Ellipse) { - cus.push(o.userData); + let reg = new Region([en.Clone() as Curve]); + app.m_Database.ModelSpace.Append(reg); + } + else if (en instanceof Curve) + { + lines.push(en.Clone() as Curve); } } - - console.log(cus.length); - let str = cus.map(cu => + if (lines.length > 0) { - console.log(`new Vector3().fromArray([${cu.StartPoint.toArray()}]), new Vector3().fromArray([${cu.EndPoint.toArray()}])`); - }).join("\n") + let reg = new RegionParse(lines); - let alg = new RegionParse(cus); - for (let r of alg.m_RegionsOutline) - { - let re = new Region(); - r.forEach(route => re.reg.add(route.curve)); - - re.ColorIndex = 1; - - app.m_Database.ModelSpace.Append(re); + for (let routes of reg.m_RegionsOutline) + { + this.AddToModelSpace(routes); + } + for (let routes of reg.m_RegionsInternal) + { + this.AddToModelSpace(routes); + } + app.m_Editor.UpdateScreen(); } - for (let r of alg.m_RegionsInternal) + } + AddToModelSpace(routeS: Set) + { + let cus: Curve[] = []; + for (let r of routeS) { - let re = new Region(); - r.forEach(route => re.reg.add(route.curve)); - re.ColorIndex = 2; - - app.m_Database.ModelSpace.Append(re); + cus.push(r.curve); } - - - // for (let r of regs[0]) - // { - // let reg = new Region(); - // reg.reg = r; - // app.m_Database.ModelSpace.Append(reg); - // } - - // for (let r of regs[1]) - // { - // let reg = new Region(); - // reg.reg = r; - // app.m_Database.ModelSpace.Append(reg); - // } + let reg = new Region(cus); + app.m_Database.ModelSpace.Append(reg); } } diff --git a/src/Add-on/DrawTestReg.ts b/src/Add-on/DrawTestReg.ts index 973dced8e..cdf5b7158 100644 --- a/src/Add-on/DrawTestReg.ts +++ b/src/Add-on/DrawTestReg.ts @@ -1,10 +1,12 @@ -import { Command } from "../Editor/CommandMachine"; -import { Vector3 } from "three"; -import { Line } from "../DatabaseServices/Line"; -import { app } from "../ApplicationServices/Application"; -import { Region } from "../DatabaseServices/Region"; -import { Move } from "../Geometry/GeUtils"; -import { RegionParse } from "../Geometry/RegionParse"; +import { Vector3 } from 'three'; + +import { app } from '../ApplicationServices/Application'; +import { Curve } from '../DatabaseServices/Curve'; +import { Line } from '../DatabaseServices/Line'; +import { Region } from '../DatabaseServices/Region'; +import { Command } from '../Editor/CommandMachine'; +import { Move } from '../Geometry/GeUtils'; +import { RegionParse, Route } from '../Geometry/RegionParse'; export class DrawRegTest implements Command { @@ -172,18 +174,12 @@ export class DrawRegTest implements Command for (let r of alg.m_RegionsOutline) { - let re = new Region(); - r.forEach(route => re.reg.add(route.curve)); - - app.m_Database.ModelSpace.Append(re); + createReg(r); } for (let r of alg.m_RegionsInternal) { - let re = new Region(); - r.forEach(route => re.reg.add(route.curve)); - - app.m_Database.ModelSpace.Append(re); + createReg(r); } // for (let r of reg[0]) @@ -207,3 +203,11 @@ export class DrawRegTest implements Command // } } } +function createReg(r: Set) +{ + let cus: Curve[] = []; + r.forEach(route => cus.push(route.curve)); + let re = new Region(cus); + app.m_Database.ModelSpace.Append(re); +} + diff --git a/src/Add-on/RevPl.ts b/src/Add-on/RevPl.ts new file mode 100644 index 000000000..9fe5363df --- /dev/null +++ b/src/Add-on/RevPl.ts @@ -0,0 +1,23 @@ +import { Command } from '../Editor/CommandMachine'; +import { SelectSet } from '../Editor/SelectSet'; +import { Polyline } from '../DatabaseServices/Polyline'; +import { app } from '../ApplicationServices/Application'; + +export class Command_RevPl implements Command +{ + async exec(ss: SelectSet) + { + + let pls: Polyline[] = []; + for (let en of ss.SelectEntityList) + { + if (en instanceof Polyline) + { + pls.push(en); + en.Reverse(); + } + } + + app.m_Editor.UpdateScreen(); + } +} diff --git a/src/ApplicationServices/mesh/createBoard.ts b/src/ApplicationServices/mesh/createBoard.ts index cb1de384f..a2818838d 100644 --- a/src/ApplicationServices/mesh/createBoard.ts +++ b/src/ApplicationServices/mesh/createBoard.ts @@ -44,10 +44,10 @@ export namespace CreateBoardUtil //创建轮廓 通过点表和凸度 - export function createPath(pts: THREE.Vector2[], buls: number[]): THREE.Shape + export function createPath(pts: THREE.Vector2[], buls: number[], shapeOut?: THREE.Shape): THREE.Shape { - var shape = new THREE.Shape(); + var shape = shapeOut || new THREE.Shape(); let firstPt = pts[0]; shape.moveTo(firstPt.x, firstPt.y); for (let i = 0; i < pts.length - 1; i++) diff --git a/src/DatabaseServices/Arc.ts b/src/DatabaseServices/Arc.ts index 395c0f712..8a5d2e0f2 100644 --- a/src/DatabaseServices/Arc.ts +++ b/src/DatabaseServices/Arc.ts @@ -7,16 +7,19 @@ import { RenderType } from '../GraphicsSystem/Enum'; import { Factory } from './CADFactory'; import { CADFile } from './CADFile'; import { Entity } from './Entity'; +import { Curve } from './Curve'; @Factory -export class Arc extends Entity +export class Arc extends Curve { - constructor(center?: Vector3, startAngle?: number, endAngle?: number) + constructor(center?: Vector3, radius?: number, startAngle?: number, endAngle?: number, normal?: Vector3) { super(); center && this.m_Center.copy(center); + normal && this.m_Normal.copy(normal); + this.m_Radius = radius || 0; this.m_StartAngle = startAngle || 0; this.m_EndAngle = endAngle || 0; } @@ -80,7 +83,18 @@ export class Arc extends Entity this.m_EndAngle = v <= 0 ? 1e-19 : v; this.Update(); } - + get StartPoint() + { + let startPoint = new Vector3(); + polar(startPoint, this.m_StartAngle, this.m_Radius); + return this.m_Center.clone().add(startPoint); + } + get EndPoint() + { + let endPoint = new Vector3(); + polar(endPoint, this.m_EndAngle, this.m_Radius); + return this.m_Center.clone().add(endPoint); + } FromThreePoint(pt1?: Vector3, pt2?: Vector3, pt3?: Vector3) { if (!(pt1 && pt2 && pt3)) diff --git a/src/DatabaseServices/Ellipse.ts b/src/DatabaseServices/Ellipse.ts index 1e8e315df..4cd5b435d 100644 --- a/src/DatabaseServices/Ellipse.ts +++ b/src/DatabaseServices/Ellipse.ts @@ -1,14 +1,15 @@ import { Factory } from "./CADFactory"; import { Entity } from "./Entity"; -import { Vector3, Geometry } from "three"; +import { Vector3, Geometry, Matrix4 } from "three"; import { RenderType } from "../GraphicsSystem/Enum"; import { ColorMaterial } from "../Common/ColorPalette"; import * as THREE from "three"; import { cZAxis } from "../Geometry/GeUtils"; import { CADFile } from "./CADFile"; +import { Curve } from './Curve'; @Factory -export class Ellipse extends Entity +export class Ellipse extends Curve { private m_Center: Vector3; private m_RadX: number; @@ -72,6 +73,12 @@ export class Ellipse extends Entity this.m_Angle // aRotation ); } + ApplyMatrix(m: Matrix4) + { + super.ApplyMatrix(m); + this.m_Center.applyMatrix4(m); + this.Update(); + } Draw(renderType: RenderType): THREE.Object3D { let obj = super.Draw(renderType); @@ -152,4 +159,4 @@ export class Ellipse extends Entity file.Write(this.Angle); } -} \ No newline at end of file +} diff --git a/src/DatabaseServices/Polyline.ts b/src/DatabaseServices/Polyline.ts index 4071ccbde..50e0be978 100644 --- a/src/DatabaseServices/Polyline.ts +++ b/src/DatabaseServices/Polyline.ts @@ -1,4 +1,4 @@ -import { Geometry, Object3D, Vector2, Vector3 } from 'three'; +import { Geometry, Object3D, Vector2, Vector3, Matrix4 } from 'three'; import * as THREE from 'three'; import { CreateBoardUtil } from '../ApplicationServices/mesh/createBoard'; @@ -8,6 +8,7 @@ import { RenderType } from '../GraphicsSystem/Enum'; import { Factory } from './CADFactory'; import { CADFile } from './CADFile'; import { Entity } from './Entity'; +import { Curve } from './Curve'; export interface PolylineData { @@ -16,7 +17,7 @@ export interface PolylineData } @Factory -export class Polyline extends Entity +export class Polyline extends Curve { private m_LineData: PolylineData[]; private m_ptList: Vector3[]; @@ -25,12 +26,44 @@ export class Polyline extends Entity super(); this.m_LineData = data || [{ pt: new Vector2(0, 0), bul: 0 }]; } + + //翻转曲线,首尾调换 + Reverse() + { + if (this.m_LineData.length === 0) + return; + this.WriteAllObjectRecord(); + + let pts = []; + let buls = []; + for (let data of this.m_LineData) + { + pts.push(data.pt); + buls.push(-data.bul); + } + buls.reverse(); + buls.push(buls[0]) + buls.shift(); + + pts.reverse(); + + this.m_LineData.length = 0; + for (let i = 0; i < pts.length; i++) + { + this.m_LineData.push({ pt: pts[i], bul: buls[i] }); + } + this.Update(); + } set LineData(data: PolylineData[]) { this.WriteAllObjectRecord(); this.m_LineData = data; this.Update(); } + get LineData() + { + return this.m_LineData; + } CreateCurve() { let pts = []; @@ -56,6 +89,32 @@ export class Polyline extends Entity return obj; } + //移动多段线 + ApplyMatrix(m: Matrix4) + { + super.ApplyMatrix(m); + for (let i of this.m_LineData) + { + let tmp = new Vector3(i.pt.x, i.pt.y, 0); + tmp.applyMatrix4(m); + i.pt.x = tmp.x; + i.pt.y = tmp.y; + } + this.Update(); + } + //多段线起点 + get StartPoint() + { + if (this.m_LineData.length > 0) + return new Vector3(this.m_LineData[0].pt.x, this.m_LineData[0].pt.y, 0); + return new Vector3(); + } + get EndPoint() + { + if (this.m_LineData.length > 0) + return new Vector3(this.m_LineData[this.m_LineData.length - 1].pt.x, this.m_LineData[this.m_LineData.length - 1].pt.y, 0); + return new Vector3(); + } Update() { for (let [, obj] of this.m_DrawEntity) diff --git a/src/DatabaseServices/Region.ts b/src/DatabaseServices/Region.ts index b9db4907f..1dbc48232 100644 --- a/src/DatabaseServices/Region.ts +++ b/src/DatabaseServices/Region.ts @@ -1,99 +1,152 @@ -import { Object3D, ShapeGeometry, Vector3 } from 'three'; import * as THREE from 'three'; +import { Object3D, ShapeGeometry, Vector3, Vector2 } from 'three'; +import { CreateBoardUtil } from '../ApplicationServices/mesh/createBoard'; import { RenderType } from '../GraphicsSystem/Enum'; +import { Arc } from './Arc'; import { Factory } from './CADFactory'; +import { CADFile } from './CADFile'; import { Circle } from './Circle'; import { Curve } from './Curve'; +import { Ellipse } from './Ellipse'; import { Entity } from './Entity'; import { Line } from './Line'; -import { ColorMaterial } from '../Common/ColorPalette'; +import { Polyline } from './Polyline'; +import { begin } from 'xaop'; + +const fuzz = 1e-8; @Factory export class Region extends Entity { - reg: Set = new Set(); - constructor() + private m_CuList: Array = []; + private m_Shape: THREE.Shape; + constructor(curveList?: Array) { super(); - } + if (curveList) + this.m_CuList.push(...curveList); + } Draw(renderType: RenderType): Object3D { - if (this.reg.size === 0) - return; - let shape = new THREE.Shape(); + let obj = super.Draw(renderType); + if (obj) return obj; - let begin = new Vector3(); - let end = new Vector3(); - let n = 0; + this.m_Shape = new THREE.Shape(); + let begin: Vector3; - let lines = []; - for (let l of this.reg) - { - lines.push(l); - } - let firstL = lines[0]; - let seconL = lines[1]; - if (firstL.StartPoint.distanceTo(seconL.StartPoint) < 0.1 - || firstL.StartPoint.distanceTo(seconL.EndPoint) < 0.1 - ) + if (this.m_CuList.length > 1) { - begin.copy(firstL.EndPoint); - end.copy(firstL.StartPoint); - } - else - { - begin.copy(firstL.StartPoint); - end.copy(firstL.EndPoint); + let firstL = this.m_CuList[0]; + let seconL = this.m_CuList[1]; + + if (firstL.StartPoint.distanceTo(seconL.StartPoint) < fuzz + || firstL.StartPoint.distanceTo(seconL.EndPoint) < fuzz + ) + { + begin = firstL.EndPoint; + } + else + { + begin = firstL.StartPoint; + } + this.m_Shape.moveTo(begin.x, begin.y); } - for (let i = 0; i < lines.length; i++) + + for (let cu of this.m_CuList) { - let cu = lines[i]; + if (cu instanceof Line) { - if (i !== 0) + if (cu.StartPoint.distanceTo(begin) < fuzz) + begin = cu.EndPoint; + else + begin = cu.StartPoint; + + this.m_Shape.lineTo(begin.x, begin.y); + } + else if (cu instanceof Circle) + { + this.m_Shape.absarc(cu.Center.x, cu.Center.y, cu.Radius, 0, 2 * Math.PI, true); + } + else if (cu instanceof Ellipse) + { + this.m_Shape.absellipse(cu.Center.x, cu.Center.y, cu.RadX, cu.RadY, 0, Math.PI * 2, true, cu.Angle); + } + else if (cu instanceof Polyline) + { + if (cu.EndPoint.distanceTo(begin) < fuzz) + cu.Reverse(); + + let plData = cu.LineData; + let pts: Vector2[] = []; + let bul: number[] = []; + for (let d of plData) { - if (end.distanceTo(cu.StartPoint) < 0.1) - { - begin.copy(cu.StartPoint); - end.copy(cu.EndPoint); - } - else - { - begin.copy(cu.EndPoint); - end.copy(cu.StartPoint); - } + pts.push(d.pt); + bul.push(d.bul); } - shape.moveTo(begin.x, begin.y); - shape.lineTo(end.x, end.y); + CreateBoardUtil.createPath(pts, bul, this.m_Shape); + + begin = cu.EndPoint; + } + else if (cu instanceof Arc) + { + //起点和终点影响开始角度,结束角度和法向量 + if (begin.distanceTo(cu.StartPoint) < 0.1) + this.m_Shape.absarc(cu.Center.x, cu.Center.y, cu.Radius, cu.StartAngle, cu.EndAngle, cu.Normal.z < 0); + else + this.m_Shape.absarc(cu.Center.x, cu.Center.y, cu.Radius, cu.EndAngle, cu.StartAngle, cu.Normal.z > 0); } } - // shape.absarc(i.Center.x, i.Center.y, i.Radius, 0, 2 * Math.PI, true); + let geometry = new ShapeGeometry(this.m_Shape, 60); + let material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); - let geometry = new ShapeGeometry(shape, 60); - let mesh = new THREE.Mesh(geometry, ColorMaterial.GetLineMaterial(this.m_Color)); + let mesh = new THREE.Mesh(geometry, material); this.m_DrawEntity.set(renderType, mesh); mesh.userData = this; return mesh; } - // Update() - // { - // for (let [, obj] of this.m_DrawEntity) - // { - // let mesh = (obj); - - // mesh.updateMorphTargets(); - // } - // } + //在移动时应用矩阵变换 ApplyMatrix(m: THREE.Matrix4) { + this.WriteAllObjectRecord(); + for (let cu of this.m_CuList) + { + cu.ApplyMatrix(m); + } for (let [, en] of this.m_DrawEntity) { en.applyMatrix(m); } + + } + //读写文件 + ReadFile(file: CADFile) + { + super.ReadFile(file); + let ver = file.Read();//1 + let cout = file.Read(); + this.m_CuList.length = 0; + for (let i = 0; i < cout; i++) + { + let obj = file.ReadObject(undefined) as Curve; + this.m_CuList.push(obj); + } + } + //对象将自身数据写入到文件. + WriteFile(file: CADFile) + { + super.WriteFile(file); + file.Write(1);//ver + file.Write(this.m_CuList.length); + for (let i of this.m_CuList) + { + file.WriteObject(i); + } } } diff --git a/src/Editor/CommandRegister.ts b/src/Editor/CommandRegister.ts index cb134e65b..dd37efaa0 100644 --- a/src/Editor/CommandRegister.ts +++ b/src/Editor/CommandRegister.ts @@ -30,6 +30,7 @@ import { DrawRegTest } from '../Add-on/DrawTestReg'; import { DrawPolyline } from '../Add-on/DrawPolyline'; import { CustomUcs } from '../Add-on/CostumUCS'; import { Command_Copy } from '../Add-on/Copy'; +import { Command_RevPl } from '../Add-on/RevPl'; // import { RevTarget, SaveTarget } from '../Add-on/RenderTarget'; export function registerCommand() @@ -88,6 +89,7 @@ export function registerCommand() commandMachine.RegisterCommand("sky", new DrawSky()); + commandMachine.RegisterCommand("reg", new DrawRegion()); commandMachine.RegisterCommand("ucs", new CustomUcs()); commandMachine.RegisterCommand("reg", new DrawRegion()); @@ -95,6 +97,10 @@ export function registerCommand() commandMachine.RegisterCommand("reg2", new DrawRegTest()); commandMachine.RegisterCommand("copy", new Command_Copy()); + + commandMachine.RegisterCommand("rev", new Command_RevPl()); + + // commandMachine.RegisterCommand("st", new SaveTarget()) // commandMachine.RegisterCommand("rt", new RevTarget()) } diff --git a/src/Geometry/RegionParse.ts b/src/Geometry/RegionParse.ts index 5ee629c82..4cdbdf40b 100644 --- a/src/Geometry/RegionParse.ts +++ b/src/Geometry/RegionParse.ts @@ -1,8 +1,9 @@ -import { Curve } from "../DatabaseServices/Curve"; -import { Vector3 } from "three"; +import { Vector3 } from 'three'; + +import { Curve } from '../DatabaseServices/Curve'; //路线 -interface Route +export interface Route { curve: Curve; //路线的曲线 to: Stand; //终点的点 @@ -37,8 +38,15 @@ export class RegionParse m_RegionsOutline: RegionRouteS = []; //区域列表 通常是内轮廓 m_RegionsInternal: RegionRouteS = []; + + /** + * Creates an instance of RegionParse. + * @param {Curve[]} cuList 请不要传递圆和椭圆. + * @memberof RegionParse + */ constructor(cuList: Curve[]) { + let circles = new Set(); //构造路线图. this.GenerateMap(cuList);