diff --git a/src/Add-on/Mirror.ts b/src/Add-on/Mirror.ts new file mode 100644 index 000000000..d34ab28f5 --- /dev/null +++ b/src/Add-on/Mirror.ts @@ -0,0 +1,69 @@ +import { Matrix4, Vector3 } from "three"; +import { app } from "../ApplicationServices/Application"; +import { Command } from "../Editor/CommandMachine"; +import { JigUtils } from "../Editor/JigUtils"; +import { PromptStatus } from "../Editor/PromptResult"; +import { MoveMatrix } from "../Geometry/GeUtils"; + +export class MirrorCommand implements Command +{ + async exec() + { + let enRes = await app.m_Editor.GetSelection({ + Msg: "选择对象", UseSelect: true + }); + if (enRes.Status === PromptStatus.Cancel) + return; + + let ens = enRes.SelectSet.SelectEntityList; + let ptRes = await app.m_Editor.GetPoint({ + Msg: "选择镜像第一点" + }); + if (ptRes.Status === PromptStatus.Cancel) + return; + + let p1 = ptRes.Value; + let cloneEns = ens.map(en => JigUtils.Draw(en)); + ptRes = await app.m_Editor.GetPoint({ + Msg: "选择镜像第二点", + BasePoint: p1, + AllowDrawRubberBand: true, + Callback: (v) => + { + JigUtils.Restore(); + let rot = new Matrix4().makeRotationAxis(p1.clone().cross(v).normalize(), Math.PI / 2); + let vec = v.clone().sub(p1).applyMatrix4(rot).normalize(); + let newMat = this.GetMirrorMat(vec); + cloneEns.forEach(en => + { + en.ApplyMatrix(MoveMatrix(p1.clone().negate())) + .ApplyMatrix(newMat) + .ApplyMatrix(MoveMatrix(p1)) + }) + } + }); + if (ptRes.Status === PromptStatus.Cancel) + return; + + let kwRes = await app.m_Editor.GetKeyWords({ + Msg: "是否删除源对象", + KeyWordList: [{ msg: "是", key: "Y" }, { msg: "否", key: "N" }] + }); + if (kwRes.Status === PromptStatus.Cancel) + return; + + JigUtils.End(); + if (kwRes.StringResult === "Y") + ens.forEach(en => en.Erase()); + cloneEns.forEach(en => app.m_Database.ModelSpace.Append(en)); + } + GetMirrorMat(v: Vector3) + { + let mirrorMat = new Matrix4(); + let xAxis = new Vector3(1 - 2 * v.x ** 2, -2 * v.x * v.y, -2 * v.x * v.z); + let yAxis = new Vector3(-2 * v.x * v.y, 1 - 2 * v.y ** 2, -2 * v.y * v.z); + let zAxis = new Vector3(-2 * v.x * v.z, -2 * v.y * v.z, 1 - 2 * v.z ** 2); + mirrorMat.makeBasis(xAxis, yAxis, zAxis); + return mirrorMat; + } +} diff --git a/src/Common/Matrix4Utils.ts b/src/Common/Matrix4Utils.ts index 0c43d2e05..c2a02f1fa 100644 --- a/src/Common/Matrix4Utils.ts +++ b/src/Common/Matrix4Utils.ts @@ -1,5 +1,6 @@ import { Matrix4, Vector3 } from 'three'; import { equaln, isParallelTo } from '../Geometry/GeUtils'; +import { CoordinateSystem } from '../Geometry/CoordinateSystem'; /** * 设置矩阵的某列的向量 @@ -78,3 +79,14 @@ export function setRotationOnAxis(mat: Matrix4, axis: Vector3, ro: number) mat.setPosition(pos); return mat; } + +/** + * 修正镜像后矩阵 + * @param m + */ +export function reviseMirrorMatrix(m: Matrix4) +{ + let cs = new CoordinateSystem().applyMatrix4(m); + cs.m_yAxis.negate(); + m.copy(cs.getMatrix4()); +} diff --git a/src/DatabaseServices/Arc.ts b/src/DatabaseServices/Arc.ts index 8b1f90d54..7ac310cf3 100644 --- a/src/DatabaseServices/Arc.ts +++ b/src/DatabaseServices/Arc.ts @@ -2,8 +2,8 @@ import * as THREE from 'three'; import { Box3, Matrix4, Object3D, Shape, ShapeGeometry, Vector2, Vector3 } from 'three'; import { ColorMaterial } from '../Common/ColorPalette'; import { getCircleCenter, getTanPtsOnArcOrCircle, Vec2DTo3D } from '../Common/CurveUtils'; -import { matrixSetVector } from '../Common/Matrix4Utils'; -import { Status, UpdateDraw } from '../Common/Status'; +import { matrixSetVector, reviseMirrorMatrix } from '../Common/Matrix4Utils'; +import { Status } from '../Common/Status'; import { ObjectSnapMode } from '../Editor/ObjectSnapMode'; import { angle, angleTo2Pi, equaln, equalv3, midPoint, MoveMatrix, polar } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; @@ -196,6 +196,20 @@ export class Arc extends Curve this.Radius = this.Radius * m.getMaxScaleOnAxis(); return this; } + protected ApplyMirrorMatrix(m: Matrix4): this + { + this.WriteAllObjectRecord(); + + let sp = this.StartPoint; + let ep = this.EndPoint; + + reviseMirrorMatrix(this.m_Matrix); + + this.m_Clockwise = !this.m_Clockwise; + this.StartPoint = sp; + this.EndPoint = ep; + return this; + } GetPointAtParam(param: number) { let an = this.GetAngleAtParam(param); diff --git a/src/DatabaseServices/Board.ts b/src/DatabaseServices/Board.ts index 0db39a06d..7b323710d 100644 --- a/src/DatabaseServices/Board.ts +++ b/src/DatabaseServices/Board.ts @@ -14,6 +14,7 @@ import { ObjectId } from './ObjectId'; import { DbPhysicalMaterial } from './PhysicalMaterial'; import { Polyline } from './Polyline'; import { Shape } from './Shape'; +import { UpdateDraw } from '../Common/Status'; export enum BoardType { @@ -387,13 +388,7 @@ export class Board extends Entity { return this.m_Shape.Explode().map(cu => cu.ApplyMatrix(this.OCS)); } - ApplyMatrix(m: Matrix4): this - { - if (equaln(m.getMaxScaleOnAxis(), 1)) - this.m_SpecOCS.multiplyMatrices(m, this.m_SpecOCS); - return super.ApplyMatrix(m); - } RotateBoard(rox: number, roy: number, roz: number) { this.WriteAllObjectRecord(); @@ -419,6 +414,12 @@ export class Board extends Entity { return this.m_Rotation; } + ApplyMatrix(m: Matrix4): this + { + if (equaln(m.getMaxScaleOnAxis(), 1)) + this.m_SpecOCS.multiplyMatrices(m, this.m_SpecOCS); + return super.ApplyMatrix(m); + } protected ApplyScaleMatrix(m: Matrix4): this { this.WriteAllObjectRecord(); @@ -426,7 +427,12 @@ export class Board extends Entity cu.ApplyMatrix(this.OCS); cu.ApplyMatrix(m); cu.ApplyMatrix(this.OCSInv); - this.Update(); + + this.Update(UpdateDraw.Geometry); + return this; + } + protected ApplyMirrorMatrix(m: Matrix4): this + { return this; } GetGripPoints(): Array diff --git a/src/DatabaseServices/Circle.ts b/src/DatabaseServices/Circle.ts index 43e7a8766..ed6ccdbd1 100644 --- a/src/DatabaseServices/Circle.ts +++ b/src/DatabaseServices/Circle.ts @@ -2,7 +2,10 @@ import * as THREE from 'three'; import { Box3, EllipseCurve, Geometry, Matrix4, Object3D, Shape, Vector3 } from 'three'; import { arrayLast, arrayRemoveDuplicateBySort } from '../Common/ArrayExt'; import { ColorMaterial } from '../Common/ColorPalette'; +import { getTanPtsOnArcOrCircle } from '../Common/CurveUtils'; +import { reviseMirrorMatrix } from '../Common/Matrix4Utils'; import { clamp } from '../Common/Utils'; +import { ObjectSnapMode } from '../Editor/ObjectSnapMode'; import { angle, equaln, MoveMatrix, polar } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; import { IntersectCircleAndArc, IntersectCircleAndCircle, IntersectLineAndCircle, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../GraphicsSystem/IntersectWith'; @@ -12,8 +15,6 @@ import { CADFile } from './CADFile'; import { Curve } from './Curve'; import { Line } from './Line'; import { Polyline } from './Polyline'; -import { ObjectSnapMode } from '../Editor/ObjectSnapMode'; -import { getTanPtsOnArcOrCircle } from '../Common/CurveUtils'; @Factory export class Circle extends Curve @@ -61,6 +62,14 @@ export class Circle extends Curve this.Radius = this.Radius * m.getMaxScaleOnAxis(); return this; } + protected ApplyMirrorMatrix(m: Matrix4): this + { + this.WriteAllObjectRecord(); + + reviseMirrorMatrix(this.m_Matrix); + + return this; + } //******************** Curve function start*****************// diff --git a/src/DatabaseServices/Entity.ts b/src/DatabaseServices/Entity.ts index a87fceee9..09e78712c 100644 --- a/src/DatabaseServices/Entity.ts +++ b/src/DatabaseServices/Entity.ts @@ -1,7 +1,7 @@ import { Box3, Geometry, Matrix4, Object3D, Vector3 } from 'three'; import { DisposeThreeObj } from '../Common/Dispose'; import { matrixIsCoplane } from '../Common/Matrix4Utils'; -import { equaln } from '../Geometry/GeUtils'; +import { equaln, equalv3 } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { Factory } from './CADFactory'; @@ -272,10 +272,18 @@ export class Entity extends CADObject ApplyMatrix(m: Matrix4): this { this.WriteAllObjectRecord(); + if (equaln(m.getMaxScaleOnAxis(), 1)) { + let xA = new Vector3(); + let yA = new Vector3(); + let zA = new Vector3(); + m.extractBasis(xA, yA, zA) this.m_Matrix.multiplyMatrices(m, this.m_Matrix); - this.Update(UpdateDraw.Matrix); + if (!equalv3(xA.clone().cross(yA).normalize(), zA)) + this.ApplyMirrorMatrix(m); + else + this.Update(UpdateDraw.Matrix); } else { @@ -287,6 +295,10 @@ export class Entity extends CADObject { return this; } + protected ApplyMirrorMatrix(m: Matrix4): this + { + return this; + } GetGripPoints(): Array { diff --git a/src/DatabaseServices/Line.ts b/src/DatabaseServices/Line.ts index b0f797bc9..be4a388e2 100644 --- a/src/DatabaseServices/Line.ts +++ b/src/DatabaseServices/Line.ts @@ -3,7 +3,9 @@ import { Box3, BufferGeometry, Matrix4, Object3D, Shape, Vector3 } from 'three'; import { arraySortByNumber } from '../Common/ArrayExt'; import { ColorMaterial } from '../Common/ColorPalette'; import { Vec3DTo2D } from '../Common/CurveUtils'; +import { reviseMirrorMatrix } from '../Common/Matrix4Utils'; import { Status } from '../Common/Status'; +import { ObjectSnapMode } from '../Editor/ObjectSnapMode'; import { BufferGeometryUtils } from '../Geometry/BufferGeometryUtils'; import { equalv3, isParallelTo, MoveMatrix } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; @@ -14,7 +16,6 @@ import { CADFile } from './CADFile'; import { Circle } from './Circle'; import { Curve } from './Curve'; import { Polyline } from './Polyline'; -import { ObjectSnapMode } from '../Editor/ObjectSnapMode'; @Factory export class Line extends Curve @@ -39,6 +40,19 @@ export class Line extends Curve this.EndPoint = this.EndPoint.applyMatrix4(m); return this; } + protected ApplyMirrorMatrix(m: Matrix4): this + { + this.WriteAllObjectRecord(); + + let sp = this.StartPoint; + let ep = this.EndPoint; + + reviseMirrorMatrix(this.m_Matrix); + + this.StartPoint = sp; + this.EndPoint = ep; + return this; + } InitDrawObject(renderType: RenderType = RenderType.Wireframe): Object3D { return new THREE.Line( diff --git a/src/DatabaseServices/Polyline.ts b/src/DatabaseServices/Polyline.ts index 57826e1ca..8fa6c45e6 100644 --- a/src/DatabaseServices/Polyline.ts +++ b/src/DatabaseServices/Polyline.ts @@ -4,7 +4,7 @@ import { CreateBoardUtil } from '../ApplicationServices/mesh/createBoard'; import { arrayLast, arrayRemoveDuplicateBySort, changeArrayStartIndex } from '../Common/ArrayExt'; import { ColorMaterial } from '../Common/ColorPalette'; import { getDeterminantFor2V, Vec2DTo3D, Vec3DTo2D } from '../Common/CurveUtils'; -import { matrixAlignCoordSys } from '../Common/Matrix4Utils'; +import { matrixAlignCoordSys, reviseMirrorMatrix } from '../Common/Matrix4Utils'; import { Status } from '../Common/Status'; import { FixIndex } from '../Common/Utils'; import { equaln, equalv3, updateGeometry, equalv2 } from '../Geometry/GeUtils'; @@ -195,6 +195,22 @@ export class Polyline extends Curve } return this; } + protected ApplyMirrorMatrix(m: Matrix4): this + { + this.WriteAllObjectRecord(); + + let oldPts = this.GetStretchPoints(); + reviseMirrorMatrix(this.m_Matrix); + for (let i = 0; i < oldPts.length; i++) + { + let newP = oldPts[i].applyMatrix4(this.OCSInv); + let newBul = -this.GetBuilgeAt(i); + this.SetPointAt(i, Vec3DTo2D(newP)); + this.SetBulgeAt(i, newBul); + } + + return this; + } SetBulgeAt(index: number, bul: number): this { let d = this.m_LineData[index]; @@ -615,7 +631,6 @@ export class Polyline extends Curve if (this.m_LineData.length === 0) this.ApplyMatrix(cu.OCS); - let ocsInv = this.OCSInv; let [cuSp2, cuEp2] = [cuSp, cuEp].map(p => Vec3DTo2D(p.clone().applyMatrix4(ocsInv))); @@ -642,6 +657,8 @@ export class Polyline extends Curve } else { + let dir = equalv3(this.Normal, cu.Normal.negate()) ? -1 : 1; + if (cu instanceof Line) { if (equalv3(cuSp, sp, fuzz)) @@ -665,7 +682,7 @@ export class Polyline extends Curve } else if (cu instanceof Arc) { - let bul = cu.Bul; + let bul = cu.Bul * dir; if (equalv3(cuSp, sp, fuzz)) { this.m_LineData.unshift({ pt: cuEp2, bul: -bul }); @@ -697,8 +714,10 @@ export class Polyline extends Curve let cuPtsBul = cu.PtsBuls; //坐标系对齐 - for (let p of cuPtsBul.pts) + for (let i = 0; i < cuPtsBul.pts.length; i++) { + let p = cuPtsBul.pts[i]; + cuPtsBul.buls[i] *= dir; p.copy(Vec3DTo2D(Vec2DTo3D(p).applyMatrix4(alMat))); } diff --git a/src/DatabaseServices/Region.ts b/src/DatabaseServices/Region.ts index 98028b4bd..9b2cb1966 100644 --- a/src/DatabaseServices/Region.ts +++ b/src/DatabaseServices/Region.ts @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { Box3, Group, Matrix4, MeshNormalMaterial, Object3D, ShapeBufferGeometry, Vector3 } from 'three'; +import { Box3, Group, Matrix4, MeshNormalMaterial, Object3D, ShapeBufferGeometry, Vector3, DoubleSide } from 'three'; import { DisposeThreeObj } from '../Common/Dispose'; import { MoveMatrix } from '../Geometry/GeUtils'; import { BoolOpeartionType } from '../GraphicsSystem/BoolOperateUtils'; @@ -13,6 +13,7 @@ import { Curve } from './Curve'; import { Entity } from './Entity'; import { Shape } from './Shape'; import { ShapeManager } from './ShapeManager'; +import { UpdateDraw } from '../Common/Status'; let mat = new MeshNormalMaterial(); @@ -107,6 +108,19 @@ export class Region extends Entity this.m_ShapeManager.ShapeList.forEach(s => s.ApplyMatrix(m)); return super.ApplyMatrix(m); } + protected ApplyScaleMatrix(m: Matrix4): this + { + this.WriteAllObjectRecord(); + for (let s of this.m_ShapeManager.ShapeList) + s.ApplyScaleMatrix(m); + + this.Update(UpdateDraw.Geometry); + return this; + } + protected ApplyMirrorMatrix(m: Matrix4) + { + return this; + } /** * 请注意:该计算会操作otherRegion的矩阵 * diff --git a/src/DatabaseServices/Shape.ts b/src/DatabaseServices/Shape.ts index 9677138ff..36c5dcbda 100644 --- a/src/DatabaseServices/Shape.ts +++ b/src/DatabaseServices/Shape.ts @@ -54,6 +54,22 @@ export class Shape { this.m_Outline.Curve.ApplyMatrix(m); this.m_Holes.forEach(h => h.Curve.ApplyMatrix(m)); + return this; + } + ApplyScaleMatrix(m: Matrix4): this + { + + let cu = this.Outline.Curve; + let cus = this.m_Holes.map(h => h.Curve); + cus.unshift(cu); + for (let c of cus) + { + c.ApplyMatrix(c.OCS); + c.ApplyMatrix(m); + c.ApplyMatrix(c.OCSInv); + } + + return this; } Explode() { diff --git a/src/Editor/CommandRegister.ts b/src/Editor/CommandRegister.ts index c764ea1b6..8ab9c21ec 100644 --- a/src/Editor/CommandRegister.ts +++ b/src/Editor/CommandRegister.ts @@ -93,6 +93,7 @@ import { ICommand } from '../UI/Components/CommandPanel/CommandList'; import { ChangeColor } from '../Add-on/ChangeColor'; import { Command_Draw2LineAngularDim } from '../Add-on/DrawDim/Draw2LineAngularDim'; import { FeedingCommand } from '../Add-on/CommandFeeding'; +import { MirrorCommand } from '../Add-on/Mirror'; export function registerCommand() { commandMachine.RegisterCommand("b", new DrawBox()) @@ -225,6 +226,8 @@ export function registerCommand() //提取走刀 commandMachine.RegisterCommand("testm", new FeedingCommand()); + commandMachine.RegisterCommand("mi", new MirrorCommand()); + /*******test ↓↓↓*********/ commandMachine.RegisterCommand("pltest", new Command_PLTest()); diff --git a/src/Geometry/CoordinateSystem.ts b/src/Geometry/CoordinateSystem.ts index beaa15969..e99502374 100644 --- a/src/Geometry/CoordinateSystem.ts +++ b/src/Geometry/CoordinateSystem.ts @@ -28,6 +28,7 @@ export class CoordinateSystem this.m_xAxis.applyMatrix4(roMat); this.m_yAxis.applyMatrix4(roMat); this.m_zAxis.applyMatrix4(roMat); + return this; } getMatrix4(): Matrix4