From 521b17a7ac12f520f60b7eec94dfdbbf77d5bc41 Mon Sep 17 00:00:00 2001 From: ZoeLeeFZ Date: Fri, 29 Nov 2019 11:37:02 +0800 Subject: [PATCH] =?UTF-8?q?!635=20=E6=8E=92=E9=92=BB=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Add-on/BoardFindModify.ts | 6 +- src/Add-on/CommandFeeding.ts | 3 +- src/Add-on/Copy.ts | 7 +- src/Add-on/CopyClip.ts | 5 +- src/Add-on/DrawBoard/BuildLayerNailTool.ts | 12 +- src/Add-on/DrawDrilling/DeleteDrill.ts | 8 +- src/Add-on/DrawDrilling/DrawDrillingTool.ts | 259 ++++++++----- src/Add-on/DrawDrilling/DrillingReactor.ts | 5 +- src/Add-on/DrawDrilling/HoleUtils.ts | 51 +++ .../DrawDrilling/ShowDrillingTemplate.ts | 12 + src/Add-on/DrawExtrude.ts | 131 +++++++ src/Add-on/Erp/ErpCommands.ts | 4 + src/Add-on/Erp/ParseData.ts | 2 +- src/Add-on/LookOverBoardInfos.ts | 40 +- src/Add-on/Print.ts | 4 +- src/Add-on/RotateLayerBoard.ts | 49 +-- src/Add-on/testEntity/test.ts | 5 +- src/Add-on/testEntity/testCollision.ts | 6 +- src/Common/AppCache.ts | 7 + src/Common/Request.ts | 1 + src/Common/SerializeMaterial.ts | 51 ++- src/Common/StoreageKeys.ts | 2 + .../3DSolid/{GangDrill.ts => CylinderHole.ts} | 112 +++--- src/DatabaseServices/3DSolid/Cylineder.ts | 4 +- src/DatabaseServices/3DSolid/ExtrudeHole.ts | 354 ++++++++++++++++++ src/DatabaseServices/3DSolid/Hole.ts | 51 +++ src/DatabaseServices/3DSolid/Solid3D.ts | 7 - src/DatabaseServices/3DSolid/SweepSolid.ts | 4 +- src/DatabaseServices/Entity/Board.ts | 23 +- src/DatabaseServices/Entity/Extrude.ts | 5 +- src/DatabaseServices/Shape.ts | 12 +- src/Editor/CommandRegister.ts | 5 + src/Editor/UserConfig.ts | 2 + src/Geometry/CreateWireframe.ts | 38 ++ src/Geometry/DrillParse/BoardGetFace.ts | 69 ++-- src/Geometry/DrillParse/CollisionDetection.ts | 28 +- src/Geometry/DrillParse/Face.ts | 70 ++-- .../ToolPath/FeedingToolPath.ts | 133 ++++++- src/Production/Product.ts | 346 +++++++++++------ src/UI/Components/Board/DrillCommon.tsx | 142 ++++++- src/UI/Components/Board/GangDrillModal.tsx | 28 +- src/UI/Components/CommandPanel/CommandList.ts | 11 + .../Components/Modal/DrillingTemplateList.tsx | 236 ++++++++++++ .../Modal/DrillingTemplateManage.tsx | 252 +++++++++++++ .../Modal/ModalStyle/DrillModal.less | 12 + .../Modal/OptionModal/DrawConfigPanel.tsx | 2 + .../Components/SourceManage/CommonPanel.tsx | 87 +++-- src/UI/Components/SourceManage/FilePanel.tsx | 1 - .../SourceManage/HandleDirComponent.tsx | 21 ++ .../Components/SourceManage/MaterialPanel.tsx | 1 - .../Components/Template/TemplateComponent.tsx | 1 - src/UI/Components/Template/Topline.less | 10 + src/UI/Components/Template/ToplineManage.tsx | 1 - src/UI/Components/TopToolBar/TopToolBar.tsx | 32 +- src/UI/IconEnum.ts | 4 +- src/UI/Store/DrillStore.ts | 69 +++- src/UI/Store/UserConfigStore.ts | 12 +- src/UI/Store/drillInterface.ts | 3 + 58 files changed, 2263 insertions(+), 595 deletions(-) create mode 100644 src/Add-on/DrawDrilling/HoleUtils.ts create mode 100644 src/Add-on/DrawDrilling/ShowDrillingTemplate.ts create mode 100644 src/Add-on/DrawExtrude.ts rename src/DatabaseServices/3DSolid/{GangDrill.ts => CylinderHole.ts} (74%) create mode 100644 src/DatabaseServices/3DSolid/ExtrudeHole.ts create mode 100644 src/DatabaseServices/3DSolid/Hole.ts delete mode 100644 src/DatabaseServices/3DSolid/Solid3D.ts create mode 100644 src/UI/Components/Modal/DrillingTemplateList.tsx create mode 100644 src/UI/Components/Modal/DrillingTemplateManage.tsx diff --git a/src/Add-on/BoardFindModify.ts b/src/Add-on/BoardFindModify.ts index a2b874efa..70ee8f101 100644 --- a/src/Add-on/BoardFindModify.ts +++ b/src/Add-on/BoardFindModify.ts @@ -4,7 +4,7 @@ import { arrayLast } from "../Common/ArrayExt"; import { EBoardKeyList } from "../Common/BoardKeyList"; import { safeEval } from "../Common/eval"; import { FixedNotZero } from "../Common/Utils"; -import { GangDrill, GangDrillType } from "../DatabaseServices/3DSolid/GangDrill"; +import { CylinderHole, GangDrillType } from "../DatabaseServices/3DSolid/CylinderHole"; import { LineAngularDimension } from "../DatabaseServices/Dimension/2LineAngularDimension"; import { AlignedDimension } from "../DatabaseServices/Dimension/AlignedDimension"; import { Board } from "../DatabaseServices/Entity/Board"; @@ -91,12 +91,12 @@ export class BoardFindModify implements Command filterTypes.push(AlignedDimension, LineAngularDimension); if (option.condition.useDrill || option.condition.useNail || option.condition.useWood) - filterTypes.push(GangDrill); + filterTypes.push(CylinderHole); let brs = (await this.GetBoards(filterTypes)) .filter(en => { - if (en instanceof GangDrill) + if (en instanceof CylinderHole) { return ((en.Type === GangDrillType.Pxl || en.Type === GangDrillType.Ymj diff --git a/src/Add-on/CommandFeeding.ts b/src/Add-on/CommandFeeding.ts index fa5576ba8..af93e1d71 100644 --- a/src/Add-on/CommandFeeding.ts +++ b/src/Add-on/CommandFeeding.ts @@ -20,8 +20,7 @@ export class FeedingCommand implements Command if (brRes.Status === PromptStatus.Cancel) return; - let brs = brRes.SelectSet.SelectEntityList - .filter((br: Board) => br.BoardModeling.length > 0) as Board[]; + let brs = brRes.SelectSet.SelectEntityList as Board[]; if (brs.length > 0) { let feedingTool = FeedingToolPath.GetInstance() as FeedingToolPath; diff --git a/src/Add-on/Copy.ts b/src/Add-on/Copy.ts index 12c11fb78..ee387b59c 100644 --- a/src/Add-on/Copy.ts +++ b/src/Add-on/Copy.ts @@ -1,6 +1,6 @@ import { app } from '../ApplicationServices/Application'; import { arrayRemoveIf } from '../Common/ArrayExt'; -import { GangDrill, GangDrillType } from '../DatabaseServices/3DSolid/GangDrill'; +import { Hole } from '../DatabaseServices/3DSolid/Hole'; import { Board } from '../DatabaseServices/Entity/Board'; import { Entity } from '../DatabaseServices/Entity/Entity'; import { Light } from '../DatabaseServices/Lights/Light'; @@ -8,6 +8,7 @@ import { Command } from '../Editor/CommandMachine'; import { JigUtils } from '../Editor/JigUtils'; import { PromptStatus } from '../Editor/PromptResult'; import { MoveMatrix } from '../Geometry/GeUtils'; +import { CylinderHole, GangDrillType } from '../DatabaseServices/3DSolid/CylinderHole'; export class Command_Copy implements Command { @@ -32,7 +33,7 @@ export class Command_Copy implements Command 需要注意板件和排钻一起被复制的时候,单板件关联的板件id可能是空的ObjectId而不是undefined */ if (orgEns.some(en => en instanceof Board)) - arrayRemoveIf(orgEns, e => e instanceof GangDrill); + arrayRemoveIf(orgEns, e => (e instanceof Hole)); let jigEns = orgEns.map(e => JigUtils.Draw(e)); while (true) @@ -60,7 +61,7 @@ export class Command_Copy implements Command { if (en instanceof Board) en.DrillList.clear();//由于实体的新建的,所以历史记录会自动保存它的最新快照 - else if (en instanceof GangDrill && en.Type === GangDrillType.Nail) + else if (en instanceof CylinderHole && en.Type === GangDrillType.Nail) { let br1: Board; let br2: Board; diff --git a/src/Add-on/CopyClip.ts b/src/Add-on/CopyClip.ts index d7265ab76..a88dad528 100644 --- a/src/Add-on/CopyClip.ts +++ b/src/Add-on/CopyClip.ts @@ -2,11 +2,10 @@ import { Box3, Vector3 } from "three"; import { app } from "../ApplicationServices/Application"; import { arrayRemoveIf } from "../Common/ArrayExt"; import { copyTextToClipboard } from "../Common/Utils"; -import { GangDrill } from "../DatabaseServices/3DSolid/GangDrill"; +import { Hole } from "../DatabaseServices/3DSolid/Hole"; import { CADFiler } from "../DatabaseServices/CADFiler"; import { Board } from "../DatabaseServices/Entity/Board"; import { PromptStatus } from "../Editor/PromptResult"; -import { deflate } from "../Common/SerializeMaterial"; export class CopyClip { @@ -18,7 +17,7 @@ export class CopyClip let ens = ss.SelectEntityList; if (ens.some(en => en instanceof Board)) - arrayRemoveIf(ens, e => e instanceof GangDrill); + arrayRemoveIf(ens, e => (e instanceof Hole)); let basePt: Vector3; diff --git a/src/Add-on/DrawBoard/BuildLayerNailTool.ts b/src/Add-on/DrawBoard/BuildLayerNailTool.ts index 5a1ecbc75..cb12c0da4 100644 --- a/src/Add-on/DrawBoard/BuildLayerNailTool.ts +++ b/src/Add-on/DrawBoard/BuildLayerNailTool.ts @@ -1,5 +1,4 @@ import { Board, BoardType } from "../../DatabaseServices/Entity/Board"; -import { GangDrill, GangDrillType } from "../../DatabaseServices/3DSolid/GangDrill"; import { LayerBoardOption, LayerNailOption } from "../../UI/Store/BoardInterface"; import { Matrix4, Vector3 } from "three"; import { MoveMatrix, equalv3 } from "../../Geometry/GeUtils"; @@ -7,6 +6,7 @@ import { ObjectId } from "../../DatabaseServices/ObjectId"; import { arrayLast } from "../../Common/ArrayExt"; import { ISpaceParse } from "../../Geometry/SpaceParse/ISpaceParse"; import { app } from "../../ApplicationServices/Application"; +import { CylinderHole, GangDrillType } from "../../DatabaseServices/3DSolid/CylinderHole"; enum NailPos { Left = 0, @@ -16,7 +16,7 @@ enum NailPos interface INailProps { pos: NailPos; - nail: GangDrill; + nail: CylinderHole; } class BuildLayerNailsTool @@ -50,7 +50,7 @@ class BuildLayerNailsTool if (this.leftBoard) { - let lNail = GangDrill.CreateCylDrill(rad, nailOpt.length, GangDrillType.Nail); + let lNail = CylinderHole.CreateCylHole(rad, nailOpt.length, GangDrillType.Nail); lNail.ApplyMatrix(new Matrix4().makeRotationX(Math.PI / 2)) .ApplyMatrix(MoveMatrix(new Vector3(frontDist, br.Height + depth + leftShrink, -rad))); initNails.push({ @@ -61,7 +61,7 @@ class BuildLayerNailsTool if (this.rightBoard) { - let rNail = GangDrill.CreateCylDrill(rad, nailOpt.length, GangDrillType.Nail); + let rNail = CylinderHole.CreateCylHole(rad, nailOpt.length, GangDrillType.Nail); rNail.ApplyMatrix(new Matrix4().makeRotationX(-Math.PI / 2)) .ApplyMatrix(MoveMatrix(new Vector3(frontDist, -depth - rightShrink, -rad))); initNails.push({ @@ -75,7 +75,7 @@ class BuildLayerNailsTool { let backShrink = (this.space.Size.y - layerOpt.frontShrink) - br.Width; - let bNail = GangDrill.CreateCylDrill(rad, nailOpt.length, GangDrillType.Nail); + let bNail = CylinderHole.CreateCylHole(rad, nailOpt.length, GangDrillType.Nail); bNail.ApplyMatrix(new Matrix4().makeRotationY(-Math.PI / 2)) .ApplyMatrix(MoveMatrix(new Vector3(br.Width + depth + backShrink, frontDist, -rad))); initNails.push({ @@ -249,7 +249,7 @@ class BuildLayerNailsTool let nId: ObjectId; if (i < oldNailIds.length) { - let nail = oldNailIds[i].Object as GangDrill; + let nail = oldNailIds[i].Object as CylinderHole; if (nail.IsErase) nail.Erase(false); if (!equalv3(nail.Normal, nailProps[i].nail.Normal)) diff --git a/src/Add-on/DrawDrilling/DeleteDrill.ts b/src/Add-on/DrawDrilling/DeleteDrill.ts index 4aa0f359e..083279356 100644 --- a/src/Add-on/DrawDrilling/DeleteDrill.ts +++ b/src/Add-on/DrawDrilling/DeleteDrill.ts @@ -3,7 +3,7 @@ import { app } from "../../ApplicationServices/Application"; import { Board } from "../../DatabaseServices/Entity/Board"; import { PromptStatus } from "../../Editor/PromptResult"; import { DrawDrillingTool } from "./DrawDrillingTool"; -import { GangDrill } from "../../DatabaseServices/3DSolid/GangDrill"; +import { CylinderHole } from "../../DatabaseServices/3DSolid/CylinderHole"; enum EDeleteDrillType { @@ -36,7 +36,7 @@ export class DeleteDrill implements Command { case EDeleteDrillType.All: promptMsg = "<全部删除>选择板件或者排钻进行删除排钻:"; - filterTypes = [Board, GangDrill]; + filterTypes = [Board, CylinderHole]; break; case EDeleteDrillType.Face: promptMsg = "<板件间排钻删除>选择板件,删除板件间关联的排钻:"; @@ -48,7 +48,7 @@ export class DeleteDrill implements Command break; case EDeleteDrillType.Drills: promptMsg = "<删除排钻>选择排钻实体进行删除:"; - filterTypes = [GangDrill]; + filterTypes = [CylinderHole]; break; default: break; @@ -62,7 +62,7 @@ export class DeleteDrill implements Command if (brRes.Status === PromptStatus.OK) { - let ens = brRes.SelectSet.SelectEntityList as (Board | GangDrill)[]; + let ens = brRes.SelectSet.SelectEntityList as (Board | CylinderHole)[]; switch (this.deleteType) { case EDeleteDrillType.All: diff --git a/src/Add-on/DrawDrilling/DrawDrillingTool.ts b/src/Add-on/DrawDrilling/DrawDrillingTool.ts index e1dde82e9..3496fda56 100644 --- a/src/Add-on/DrawDrilling/DrawDrillingTool.ts +++ b/src/Add-on/DrawDrilling/DrawDrillingTool.ts @@ -6,9 +6,8 @@ import { EBoardKeyList } from "../../Common/BoardKeyList"; import { safeEval } from "../../Common/eval"; import { Singleton } from "../../Common/Singleton"; import { FixedNotZero } from "../../Common/Utils"; -import { GangDrill, GangDrillType } from "../../DatabaseServices/3DSolid/GangDrill"; +import { CylinderHole, GangDrillType } from "../../DatabaseServices/3DSolid/CylinderHole"; import { Board } from "../../DatabaseServices/Entity/Board"; -import { Circle } from "../../DatabaseServices/Entity/Circle"; import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { GroupRecord } from "../../DatabaseServices/GroupTableRecord"; import { ObjectId } from "../../DatabaseServices/ObjectId"; @@ -16,24 +15,32 @@ import { IsPointInPolyLine } from "../../DatabaseServices/PointInPolyline"; import { userConfig } from "../../Editor/UserConfig"; import { CollisionDetection } from "../../Geometry/DrillParse/CollisionDetection"; import { Face } from "../../Geometry/DrillParse/Face"; -import { equaln, MoveMatrix, ZAxis } from "../../Geometry/GeUtils"; +import { equaln, MoveMatrix, ZAxis, isParallelTo, YAxis } from "../../Geometry/GeUtils"; import { FaceDirection } from "../../UI/Store/BoardInterface"; import { DrillingOption, SpacingType } from "../../UI/Store/drillInterface"; +import { appCache } from "../../Common/AppCache"; +import { StoreageKeys } from "../../Common/StoreageKeys"; +import { PostJson, RequestStatus } from "../../Common/Request"; +import { TemplateUrls } from "../../Common/HostUrl"; +import { inflate, ExtrudeDrillFileIn } from "../../Common/SerializeMaterial"; import { Entity } from "../../DatabaseServices/Entity/Entity"; - +import { Box3Ext } from "../../Geometry/Box"; +import { Line } from "../../DatabaseServices/Entity/Line"; +import { ExtrudeHole } from "../../DatabaseServices/3DSolid/ExtrudeHole"; +import { Hole } from "../../DatabaseServices/3DSolid/Hole"; export class DrawDrillingTool extends Singleton { private m_MoveDistList: number[] = []; private m_Face: Face; private m_Option: DrillingOption; - private drillEnts: GangDrill[] = []; - private woodPins: GangDrill[] = []; + private woodPins: CylinderHole[] = []; + private drillEnts: Hole[] = []; //缓存相同碰撞面的配置 private _configCache: Map = new Map(); //缓存相同碰撞面得初始排钻 - private _drillEntsCache: Map = new Map(); - private _woodPinsCache: Map = new Map(); + private _drillEntsCache: Map = new Map(); + private _woodPinsCache: Map = new Map(); constructor() { super(); @@ -57,12 +64,12 @@ export class DrawDrillingTool extends Singleton } private GetRuleByFace(f: Face) { - let length = f.m_Length; - let key = f.drillType + "-" + FixedNotZero(length, 2); + let length = f.Length; + let key = f.DrillType + "-" + FixedNotZero(length, 2); if (this._configCache.has(key)) return this._configCache.get(key); - const rules = this.GetDrillingConfig(f.drillType); + const rules = this.GetDrillingConfig(f.DrillType); for (let rule of rules) { let startDist = rule.startDist; @@ -86,17 +93,17 @@ export class DrawDrillingTool extends Singleton let ljgDepth = this.m_Option.wdepth; //大孔半径 let bigRad = this.m_Option.wbHoleRad; - let pxlEnt: GangDrill; + let pxlEnt: CylinderHole; if (bigRad) { - pxlEnt = GangDrill.CreateCylDrill(bigRad, pxlDepth, GangDrillType.WoodPXL); + pxlEnt = CylinderHole.CreateCylHole(bigRad, pxlDepth, GangDrillType.WoodPXL); pxlEnt.ColorIndex = 6; this.woodPins.push(pxlEnt); //将三个实体移动到相应的位置 pxlEnt.ApplyMatrix(new Matrix4().makeRotationX(Math.PI / 2)); } - let ljgEnt = GangDrill.CreateCylDrill(ljgRad, ljgLength + ljgDepth, GangDrillType.Wood); + let ljgEnt = CylinderHole.CreateCylHole(ljgRad, ljgLength + ljgDepth, GangDrillType.Wood); ljgEnt.ColorIndex = 6; this.woodPins.push(ljgEnt); @@ -113,51 +120,90 @@ export class DrawDrillingTool extends Singleton } } - let isPostive = this.m_Face.m_InterBoard.BoardProcessOption.bigHoleDir === FaceDirection.Front; + let isPostive = this.m_Face.InterBoard.BoardProcessOption.bigHoleDir === FaceDirection.Front; for (let d of this.woodPins) { d.ApplyMatrix(MoveMatrix(ZAxis.clone().multiplyScalar(-ljgLength))); if (d.Type === GangDrillType.WoodPXL) { d.ApplyMatrix(MoveMatrix( - new Vector3(0, isPostive ? this.m_Face.m_Width : pxlDepth) + new Vector3(0, isPostive ? this.m_Face.Width : pxlDepth) )); } else { //木销位置 - let posHeight = safeEval(this.m_Option.woodPinPos, { H: this.m_Face.m_Width }); + let posHeight = safeEval(this.m_Option.woodPinPos, { H: this.m_Face.Width }); if (!isNaN(posHeight)) - d.ApplyMatrix(MoveMatrix(new Vector3(0, isPostive ? this.m_Face.m_Width - posHeight : posHeight))); + d.ApplyMatrix(MoveMatrix(new Vector3(0, isPostive ? this.m_Face.Width - posHeight : posHeight))); } } } + get CacheKey() + { + let isPostive = this.IsPostive; + return this.m_Face.DrillType + "-" + FixedNotZero(this.m_Face.Length, 2) + "-" + FixedNotZero(this.m_Face.Width, 2) + isPostive + this.m_Face.isEqualType; + } + get IsPostive() + { + return this.m_Face.InterBoard.BoardProcessOption.bigHoleDir === FaceDirection.Front; + } //初始化排钻实体 private InitDrill() + { + //缓存初始化排钻 + let key = this.CacheKey; + + if (this._drillEntsCache.has(key)) + { + this.drillEnts.push(...this._drillEntsCache.get(key)); + } + else + { + //初始化排钻 + this._InitDrill(); + this._drillEntsCache.set(key, this.drillEnts.slice() as CylinderHole[]); + } + + if (this.m_Option.isDrawWood) + { + if (this._woodPinsCache.has(key)) + { + this.woodPins.push(...this._woodPinsCache.get(key)); + } + else + { + this.InitWoodPins(); + this._woodPinsCache.set(key, this.woodPins.slice()); + } + } + } + //初始化排钻实体 + private _InitDrill() { //绘制排钻实体,在WCS0点上. let pxlDepth = this.m_Option.pxlDepth; let ljgRad = this.m_Option.ljgRad; let ljgLength = this.m_Option.ljgLength; - let pxlEnt: GangDrill; + let pxlEnt: CylinderHole; if (this.m_Option.pxlRad) { - pxlEnt = GangDrill.CreateCylDrill(this.m_Option.pxlRad, pxlDepth, GangDrillType.Pxl); + pxlEnt = CylinderHole.CreateCylHole(this.m_Option.pxlRad, pxlDepth, GangDrillType.Pxl); this.drillEnts.push(pxlEnt); //将三个实体移动到相应的位置 pxlEnt.ApplyMatrix(new Matrix4().makeRotationX(Math.PI / 2)); } - let ljgEnt = GangDrill.CreateCylDrill(ljgRad, ljgLength, GangDrillType.Ljg); + let ljgEnt = CylinderHole.CreateCylHole(ljgRad, ljgLength, GangDrillType.Ljg); this.drillEnts.push(ljgEnt); //如果都是侧面,不要预埋件,多个偏心轮 if (!this.m_Face.isEqualType) { - let ymjEnt = GangDrill.CreateCylDrill(this.m_Option.ymjRad, this.m_Option.ymjDepth, GangDrillType.Ymj); + let ymjEnt = CylinderHole.CreateCylHole(this.m_Option.ymjRad, this.m_Option.ymjDepth, GangDrillType.Ymj); ymjEnt.ApplyMatrix(new Matrix4().setPosition(new Vector3(0, 0, ljgLength))); this.drillEnts.push(ymjEnt); } @@ -172,29 +218,68 @@ export class DrawDrillingTool extends Singleton } } - let isPostive = this.m_Face.m_InterBoard.BoardProcessOption.bigHoleDir === FaceDirection.Front; + let isPostive = this.IsPostive; for (let d of this.drillEnts) { d.ApplyMatrix(MoveMatrix(ZAxis.clone().multiplyScalar(-ljgLength))); - if (d.Type === GangDrillType.Pxl) + if ((d).Type === GangDrillType.Pxl) { //偏心轮下偏距离 let pxlOffestDist = this.m_Option.pxlOffset; d.ApplyMatrix(MoveMatrix( - new Vector3(0, isPostive ? this.m_Face.m_Width - pxlOffestDist : pxlDepth - pxlOffestDist) + new Vector3(0, this.IsPostive ? this.m_Face.Width - pxlOffestDist : pxlDepth - pxlOffestDist) )); } else { //连接杆位置 - let posHeight = safeEval(this.m_Option.ljgPos, { H: this.m_Face.m_Width }); + let posHeight = safeEval(this.m_Option.ljgPos, { H: this.m_Face.Width }); if (!isNaN(posHeight)) - d.ApplyMatrix(MoveMatrix(new Vector3(0, isPostive ? this.m_Face.m_Width - posHeight : posHeight))); + d.ApplyMatrix(MoveMatrix(new Vector3(0, isPostive ? this.m_Face.Width - posHeight : posHeight))); } } } + InitDrillTemp(suitableOption: DrillingOption) + { + let key = StoreageKeys.DrillTemp + suitableOption.tempId; + let ens: ExtrudeHole[] = []; + if (appCache.has(key)) + { + ens = appCache.get(key); + } + else + { + console.error(key + "没缓存"); + return false; + } + if (!ens || ens.length === 0) return false; + this.drillEnts = ens.map(e => e.Clone()); + let isPostive = this.IsPostive; + for (let d of this.drillEnts) + { + if (isParallelTo(d.Normal, YAxis)) + { + // //偏心轮下偏距离 + let pxlOffestDist = -this.m_Option.pxlOffset; + let pos = d.Position; + let box = d.BoundingBox; + if (!this.IsPostive) + pos.add(new Vector3(0, -box.min.y)); + else + pos.add(new Vector3(0, this.m_Face.Width - box.max.y)); + d.Position = pos.add(new Vector3(0, pxlOffestDist)); + } + else + { + let posHeight = safeEval(this.m_Option.ljgPos, { H: this.m_Face.Width }); + if (!isNaN(posHeight)) + d.ApplyMatrix(MoveMatrix(new Vector3(0, isPostive ? this.m_Face.Width - posHeight : posHeight))); + } + } + return true; + } //间距等分 private EqulalSpacing() { @@ -202,12 +287,12 @@ export class DrawDrillingTool extends Singleton let endDist = this.m_Option.retDist; let count = this.m_Option.count; - let length = this.m_Face.m_Length; + let length = this.m_Face.Length; let spacingSize: number; let caclDist: Function; //是否从面坐标原点开始算 - let isFromOrigin = this.m_Face.IsPositiveFace; + let isFromOrigin = true; let dir = isFromOrigin ? 1 : -1;//排钻移动方向 @@ -215,7 +300,7 @@ export class DrawDrillingTool extends Singleton if (this.m_Option.isForceDiv) { - spacingSize = (this.m_Face.m_Length) / (count + 1); + spacingSize = (this.m_Face.Length) / (count + 1); originDist = spacingSize; } else @@ -227,7 +312,7 @@ export class DrawDrillingTool extends Singleton caclDist = (i) => spacingSize * (i - 1) * dir; //排钻初始移动距离 - this.m_MoveDistList.push(isFromOrigin ? originDist : this.m_Face.m_Length - originDist); + this.m_MoveDistList.push(isFromOrigin ? originDist : this.m_Face.Length - originDist); //加入从第一个排钻开始的移动距离 for (let i = 2; i <= count; i++) @@ -239,16 +324,16 @@ export class DrawDrillingTool extends Singleton let startDist = this.m_Option.originDist; let endDist = this.m_Option.retDist; let count = this.m_Option.count; - let length = this.m_Face.m_Length; + let length = this.m_Face.Length; let spacingSize: number; let caclDist: Function; //是否从面坐标原点开始算 - let isFromOrigin = this.m_Face.IsPositiveFace !== this.m_Option.isFromBack; + let isFromOrigin = !this.m_Option.isFromBack; let dir = isFromOrigin ? 1 : -1;//排钻移动方向 //排钻初始移动距离 - this.m_MoveDistList.push(isFromOrigin ? startDist : this.m_Face.m_Length - startDist); + this.m_MoveDistList.push(isFromOrigin ? startDist : this.m_Face.Length - startDist); let retDist = length - startDist; //是否等比例 @@ -287,27 +372,23 @@ export class DrawDrillingTool extends Singleton private BuildDrill() { let newDrillentList: ObjectId[][] = []; - - for (let i = 0; i < this.m_MoveDistList.length; i++) + let box = new Box3(); + this.drillEnts.forEach(e => box.union(e.BoundingBox)); + for (let dist of this.m_MoveDistList) { - let dist = this.m_MoveDistList[i]; - if (this.CheckModelingCollision(this.m_Face.m_InterBoard, this.drillEnts[0], dist)) - continue; - //检测排钻是否在板件内 - if (userConfig.openExactDrill && !this.CheckDrillInBoard(this.m_Face.m_InterBoard, this.drillEnts[0], dist)) + if (this.CheckModelingCollision(box, dist)) continue; - let ymjEnt = this.drillEnts.find(e => e.Type === GangDrillType.Ymj); - - if (ymjEnt && this.CheckModelingCollision(this.m_Face.m_LocalBoard, ymjEnt, dist)) + if (!this.CheckDrillInBoard(dist, box)) continue; + //新的排钻列表 let newDrillEnts: ObjectId[] = []; for (let d of this.drillEnts) { let cloneD = d.Clone(); - cloneD.MId = this.m_Face.m_InterBoard.Id; - cloneD.FId = this.m_Face.m_LocalBoard.Id; + cloneD.MId = this.m_Face.InterBoard.Id; + cloneD.FId = this.m_Face.LocalBoard.Id; cloneD.ApplyMatrix(MoveMatrix(new Vector3(dist))) .ApplyMatrix(this.m_Face.OCS); app.Database.ModelSpace.Append(cloneD); @@ -343,8 +424,8 @@ export class DrawDrillingTool extends Singleton for (let d of this.woodPins) { let cloneD = d.Clone(); - cloneD.MId = this.m_Face.m_InterBoard.Id; - cloneD.FId = this.m_Face.m_LocalBoard.Id; + cloneD.MId = this.m_Face.InterBoard.Id; + cloneD.FId = this.m_Face.LocalBoard.Id; cloneD.ApplyMatrix(MoveMatrix(new Vector3(dist))) .ApplyMatrix(this.m_Face.OCS); app.Database.ModelSpace.Append(cloneD); @@ -353,39 +434,39 @@ export class DrawDrillingTool extends Singleton woodPinss.push(newWoodEnts); } } - - this.ParseDrillList(newDrillentList, woodPinss); + if (newDrillentList.length > 0) + this.ParseDrillList(newDrillentList, woodPinss); } - //排钻避开造型 - private CheckModelingCollision(br: Board, en: GangDrill, dist: number) + private CheckDrillInBoard(dist: number, box: Box3) { - let mat = br.OCSInv.multiply(this.m_Face.OCS).multiply(MoveMatrix(new Vector3(dist))); - let modelings = br.BoardModeling; - let pos = en.Position.applyMatrix4(mat); - - for (let m of modelings) + let br = this.m_Face.InterBoard; + let cu = br.ContourCurve; + if (this.drillEnts[0] instanceof ExtrudeHole) { - let cu = m.shape.Outline.Curve; - pos.setZ(cu.Position.z); - //排钻在造型内或者和造型碰撞 - if (cu.PtInCurve(pos) || cu.IntersectWith(new Circle(pos, en.Radius), 0).length > 0) - { - return m.thickness === br.Thickness || en.Height > br.Thickness - m.thickness; - } + //TODO:先不判断自定义排钻和造型碰撞 + return true; + } + else + { + let p = this.drillEnts[0].Position.setX(dist).applyMatrix4(this.m_Face.OCS).applyMatrix4(br.OCSInv).setZ(0); + return IsPointInPolyLine(cu as Polyline, p); } - return false; } - private CheckDrillInBoard(br: Board, en: GangDrill, dist: number) + private CheckModelingCollision(box: Box3, dist: number) { - let cu = br.ContourCurve; - let p = en.Position.setX(dist).applyMatrix4(this.m_Face.OCS).applyMatrix4(br.OCSInv).setZ(0); - return IsPointInPolyLine(cu as Polyline, p); + return [this.m_Face.InterBoard, this.m_Face.LocalBoard].some(b => + { + let mat = b.OCSInv.multiply(this.m_Face.OCS).multiply(MoveMatrix(new Vector3(dist))); + let bo = box.clone().applyMatrix4(mat) as Box3Ext; + return b.Grooves.some(g => g.BoundingBox.applyMatrix4(b.OCSInv).intersectsBox(bo)); + }); + } // 分析当前排钻 private ParseDrillList(drills: ObjectId[][], woodPinss: ObjectId[][]) { - let locaBoard = this.m_Face.m_LocalBoard; - let intBoard = this.m_Face.m_InterBoard; + let locaBoard = this.m_Face.LocalBoard; + let intBoard = this.m_Face.InterBoard; let refDrillList: ObjectId[][] = []; //加入本地的板件排钻测试通孔 @@ -395,7 +476,7 @@ export class DrawDrillingTool extends Singleton refDrillList.push(...v.filter(ds => ds.length > 0 && ds[0].Object && !ds[0].IsErase)); } - if (refDrillList.length > 0) + if (refDrillList.length > 0 && drills[0][0].Object instanceof CylinderHole) { this.ParseThroughHole(drills, refDrillList, woodPinss); } @@ -439,16 +520,16 @@ export class DrawDrillingTool extends Singleton { let drillent = drills[i]; let isThought = false; - let ymjEnt = (arrayLast(drillent).Object as GangDrill); + let ymjEnt = (arrayLast(drillent).Object as CylinderHole); let p1 = ymjEnt.Position; for (let refDrill of refDrillList) { if (isThoughtDrillsSet.has(refDrill)) continue; - let refYmjEnt = (arrayLast(refDrill).Object as GangDrill); + let refYmjEnt = (arrayLast(refDrill).Object as CylinderHole); let p2 = refYmjEnt.Position; let vec = p2.sub(p1); - if (equaln(vec.length(), this.m_Face.m_LocalBoard.Thickness)) + if (equaln(vec.length(), this.m_Face.LocalBoard.Thickness)) { isThought = true; isThoughtDrillsSet.add(refDrill); @@ -506,7 +587,7 @@ export class DrawDrillingTool extends Singleton let boxes: Box3[] = [box]; for (let id of ids) { - let d = id.Object as GangDrill; + let d = id.Object as CylinderHole; if (d.Type === GangDrillType.Pxl) { boxes.push(d.BoundingBox); @@ -520,7 +601,7 @@ export class DrawDrillingTool extends Singleton //排钻是不是通孔 const isTK = (ds: ObjectId[]) => { - return ds.some(d => (d.Object as GangDrill).Type === GangDrillType.TK); + return ds.some(d => (d.Object as CylinderHole).Type === GangDrillType.TK); }; for (let i = 0; i < drills.length; i++) @@ -587,20 +668,20 @@ export class DrawDrillingTool extends Singleton //清理掉已经存在的排钻 this.ClearExitDrilling(brs); - for (let f of checkRes.m_CollisonFaces) + for (let f of checkRes.CollisonFaces) { let suitableOption = this.GetRuleByFace(f); if (!suitableOption) { - app.Editor.Prompt("长度" + f.m_Length + "没有合适的规则,或者当前配置不存在" + f.drillType + "类型排钻"); + app.Editor.Prompt("长度" + f.Length + "没有合适的规则,或者当前配置不存在" + f.DrillType + "类型排钻"); continue; } let notGangDist = suitableOption.notGangDist; //板厚小于设定厚度不排钻,或者排钻数量为0,不允许侧面同侧面 - if (f.m_LocalBoard.Thickness < notGangDist - || f.m_InterBoard.Thickness < notGangDist - || f.m_Width < notGangDist - || f.m_Width + 0.5 < f.m_InterBoard.Thickness + if (f.LocalBoard.Thickness < notGangDist + || f.InterBoard.Thickness < notGangDist + || f.Width < notGangDist + || f.Width + 0.5 < f.InterBoard.Thickness || suitableOption.count === 0 || (!suitableOption.canSameType && f.isEqualType) ) @@ -609,20 +690,16 @@ export class DrawDrillingTool extends Singleton //初始化排钻工具 this.InitTool(f, suitableOption); - //缓存初始化排钻 - let isPostive = this.m_Face.m_InterBoard.BoardProcessOption.bigHoleDir === FaceDirection.Front; - let key = f.drillType + "-" + FixedNotZero(f.m_Length, 2) + "-" + FixedNotZero(f.m_Width, 2) + isPostive + f.isEqualType; - if (this._drillEntsCache.has(key)) + if (suitableOption.useTemp && suitableOption.tempId) { - this.drillEnts.push(...this._drillEntsCache.get(key)); + let status = this.InitDrillTemp(suitableOption); + if (!status) continue; } else { - //初始化排钻 this.InitDrill(); - this._drillEntsCache.set(key, this.drillEnts.slice()); } - + let key = this.CacheKey; if (suitableOption.isDrawWood) { if (this._woodPinsCache.has(key)) diff --git a/src/Add-on/DrawDrilling/DrillingReactor.ts b/src/Add-on/DrawDrilling/DrillingReactor.ts index 69b3c54f4..370323253 100644 --- a/src/Add-on/DrawDrilling/DrillingReactor.ts +++ b/src/Add-on/DrawDrilling/DrillingReactor.ts @@ -1,10 +1,10 @@ import { app } from "../../ApplicationServices/Application"; -import { GangDrill } from "../../DatabaseServices/3DSolid/GangDrill"; import { Board } from "../../DatabaseServices/Entity/Board"; import { userConfig } from "../../Editor/UserConfig"; import { DrawDrillingTool } from "./DrawDrillingTool"; import { GroupRecord } from "../../DatabaseServices/GroupTableRecord"; import { ObjectId } from "../../DatabaseServices/ObjectId"; +import { Hole } from "../../DatabaseServices/3DSolid/Hole"; //禁止触发反应的命令 const ForbidReactorCmd = ['DELETEDRILL', 'PZ', 'ENT', 'ERASE']; @@ -24,7 +24,7 @@ export class DrillingReactor let holeGroupSet: WeakSet = new WeakSet(); for (let en of createObjects) { - if (en instanceof GangDrill) + if (en instanceof Hole) { if (!en.GourpId || holeGroupSet.has(en.GourpId)) continue; @@ -50,6 +50,7 @@ export class DrillingReactor let brs = [...createObjects, ...changeObjects] .filter(e => !e.IsErase && e instanceof Board) as Board[]; this.StartReactor(brs); + app.Editor.UpdateScreen(); }); } private GetSurroundBoards(brList: Board[]) diff --git a/src/Add-on/DrawDrilling/HoleUtils.ts b/src/Add-on/DrawDrilling/HoleUtils.ts new file mode 100644 index 000000000..6dea5f1ee --- /dev/null +++ b/src/Add-on/DrawDrilling/HoleUtils.ts @@ -0,0 +1,51 @@ +import { Board } from "../../DatabaseServices/Entity/Board"; +import { Curve } from "../../DatabaseServices/Entity/Curve"; +import { Polyline } from "../../DatabaseServices/Entity/Polyline"; +import { Vector3 } from "three"; + +export function GetHoleCurves(br: Board) +{ + let con = br.ContourCurve.Clone() as Polyline; + + let cus: Curve[] = []; + + if (br.IsSpecialShape) + { + //板构建曲线方向 + let dir = Math.sign(br.ContourCurve.Area2); + //让板件轮廓统一逆时针 + if (dir < 0) + con.Reverse(); + + let cs = con.Explode(); + while (cs.length > 0) + { + let c = cs.shift();//取第一个 + + while (true) + { + let deleteCount = 0; + for (let i = 0; i < cs.length; i++) + { + if (!c.Join(cs[i])) + { + deleteCount = cs.splice(0, i).length; + break; + } + } + //如果c和剩余的轮廓都不相交,那么退出 + if (deleteCount === 0) + { + cus.push(c); + break; + } + } + + } + } + else + { + cus = new Polyline().RectangleFrom2Pt(new Vector3(), new Vector3(br.Width, br.Height)).Explode(); + } + return cus; +} diff --git a/src/Add-on/DrawDrilling/ShowDrillingTemplate.ts b/src/Add-on/DrawDrilling/ShowDrillingTemplate.ts new file mode 100644 index 000000000..5d4caf341 --- /dev/null +++ b/src/Add-on/DrawDrilling/ShowDrillingTemplate.ts @@ -0,0 +1,12 @@ +import { Command } from "../../Editor/CommandMachine"; +import { app } from "../../ApplicationServices/Application"; +import { ModalPosition } from "../../UI/Components/Modal/ModalsManage"; +import { DrillingTemplateManage } from "../../UI/Components/Modal/DrillingTemplateManage"; + +export class ShowDrillingTemplate implements Command +{ + async exec() + { + app.Editor.ModalManage.RenderModal(DrillingTemplateManage, ModalPosition.Center, {}); + } +} diff --git a/src/Add-on/DrawExtrude.ts b/src/Add-on/DrawExtrude.ts new file mode 100644 index 000000000..9a61ef870 --- /dev/null +++ b/src/Add-on/DrawExtrude.ts @@ -0,0 +1,131 @@ +import { Matrix4, Vector3 } from "three"; +import { app } from "../ApplicationServices/Application"; +import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole"; +import { Circle } from "../DatabaseServices/Entity/Circle"; +import { ExtureContourCurve } from "../DatabaseServices/Entity/Extrude"; +import { Polyline } from "../DatabaseServices/Entity/Polyline"; +import { Command } from "../Editor/CommandMachine"; +import { JigUtils } from "../Editor/JigUtils"; +import { PromptEntityResult, PromptStatus } from "../Editor/PromptResult"; +import { isParallelTo, equalv3 } from "../Geometry/GeUtils"; + +export class DrawExtrude implements Command +{ + async exec() + { + let contour: ExtureContourCurve; + let contourRes: PromptEntityResult; + while (true) + { + contourRes = await app.Editor.GetEntity({ + Msg: "选择封闭的轮廓", + Filter: { + filterTypes: [Polyline, Circle], + filterFunction: (obj, en: ExtureContourCurve) => en.IsClose + } + }); + + if (contourRes.Status === PromptStatus.OK && contourRes.Entity) + { + contour = contourRes.Entity.Clone() as ExtureContourCurve; + break; + } + else if (contourRes.Status === PromptStatus.Cancel) + break; + } + if (!contour) return; + + let oldUcs = app.Editor.UCSMatrix; + let en = JigUtils.Draw(new ExtrudeHole()); + let appleMat = ExtrudeApplyContour(en, contour); + en.ApplyMatrix(new Matrix4().getInverse(appleMat)); + app.Editor.UCSMatrix = contour.OCS.setPosition(new Vector3); + let oldPosition = en.Position; + + let basePt: Vector3; + if (contourRes.Entity instanceof Circle) + basePt = contourRes.Entity.Center; + else + basePt = contourRes.Entity.BoundingBox.getCenter(new Vector3); + + let distRes = await app.Editor.GetDistance({ + Msg: "请输入厚度,或者点取距离", + Default: 1, + BasePoint: basePt, + Callback: (d) => + { + this.SetHeight(en, d, basePt, oldPosition); + } + }); + if (distRes.Status !== PromptStatus.OK) + { + app.Editor.UCSMatrix = oldUcs; + return; + } + this.SetHeight(en, distRes.Distance, basePt, oldPosition); + app.Editor.UCSMatrix = oldUcs; + + let radRes = await app.Editor.GetDistance({ + Msg: "请输入走刀半径", + Default: 3, + }) + + if (radRes.Status !== PromptStatus.OK) return; + en.KnifeRadius = radRes.Distance; + app.Database.ModelSpace.Append(en); + contourRes.Entity.Erase(); + } + private SetHeight(en: ExtrudeHole, dist: number, basePt: Vector3, oldPosition: Vector3) + { + en.Height = dist; + let nor = en.Normal; + let vNor = app.Viewer.WorldToScreen(nor.clone()).setZ(0); + vNor = vNor.setY(app.Viewer.Height - vNor.y); + + let vZero = app.Viewer.WorldToScreen(new Vector3); + vZero = vZero.setY(app.Viewer.Height - vZero.y); + vNor.sub(vZero); + + let curPt = app.Editor.MouseCtrl.m_CurMousePointVCS.clone(); + curPt = curPt.setY(app.Viewer.Height - curPt.y); + + let vBasePt = app.Viewer.WorldToScreen(basePt.clone()).setZ(0); + vBasePt = vBasePt.setY(app.Viewer.Height - vBasePt.y); + + let dir = curPt.sub(vBasePt); + + if (vNor.angleTo(dir) <= Math.PI / 2) + en.Position = oldPosition; + else + en.Position = oldPosition.clone().add(nor.multiplyScalar(-dist)); + } +} + + +export function ExtrudeApplyContour(ext: ExtrudeHole, contour: ExtureContourCurve): Matrix4 | undefined +{ + let applyMatrix: Matrix4; + + contour = contour.Clone(); + if (equalv3(ext.Normal, contour.Normal)) + applyMatrix = ext.OCSInv; + else if (equalv3( + contour.Normal, + new Vector3().setFromMatrixColumn(app.Editor.UCSMatrix, 2) + )) + applyMatrix = app.Editor.UCSMatrixInv; + else + applyMatrix = contour.OCSInv; + + contour.ApplyMatrix(applyMatrix); + + let box = contour.BoundingBox; + contour.Position = contour.Position.sub(box.min); + ext.ContourCurve = contour; + + //修正矩阵的基点 + applyMatrix.elements[12] -= box.min.x; + applyMatrix.elements[13] -= box.min.y; + applyMatrix.elements[14] -= box.min.z; + return applyMatrix; +} diff --git a/src/Add-on/Erp/ErpCommands.ts b/src/Add-on/Erp/ErpCommands.ts index 2915e5d97..e4dde2620 100644 --- a/src/Add-on/Erp/ErpCommands.ts +++ b/src/Add-on/Erp/ErpCommands.ts @@ -8,12 +8,16 @@ import { StoreageKeys } from "../../Common/StoreageKeys"; import { ErpParseData } from "./ParseData"; import { ErpRouteInfo } from "./Models/ErpRouteInfo"; import { ErpRoutes } from "./Models/ErpRoutes"; +import { Board } from "../../DatabaseServices/Entity/Board"; export class ChaiDan implements Command { async exec() { let selction = await app.Editor.GetSelection({ UseSelect: true, + Filter: { + filterTypes: [Board] + } }); if (selction.Status != PromptStatus.OK) return; let store = BoardStore.GetInstance() as BoardStore; diff --git a/src/Add-on/Erp/ParseData.ts b/src/Add-on/Erp/ParseData.ts index 902c28290..468b9edb3 100644 --- a/src/Add-on/Erp/ParseData.ts +++ b/src/Add-on/Erp/ParseData.ts @@ -1,6 +1,6 @@ import { Vector3 } from "three"; import { EBoardKeyList } from "../../Common/BoardKeyList"; -import { GangDrillType } from "../../DatabaseServices/3DSolid/GangDrill"; +import { GangDrillType } from "../../DatabaseServices/3DSolid/CylinderHole"; import { Board } from "../../DatabaseServices/Entity/Board"; import { Entity } from "../../DatabaseServices/Entity/Entity"; import { ExtrudeSolid } from "../../DatabaseServices/Entity/Extrude"; diff --git a/src/Add-on/LookOverBoardInfos.ts b/src/Add-on/LookOverBoardInfos.ts index 6b3fa46dd..83d3208d4 100644 --- a/src/Add-on/LookOverBoardInfos.ts +++ b/src/Add-on/LookOverBoardInfos.ts @@ -4,9 +4,10 @@ import { Command } from "../Editor/CommandMachine"; import { PromptStatus } from "../Editor/PromptResult"; import { LookOverBoardInfosModal } from "../UI/Components/Board/LookOverBoardInfos"; import { ModalPosition } from "../UI/Components/Modal/ModalsManage"; -import { GangDrill, GangDrillType } from "../DatabaseServices/3DSolid/GangDrill"; import { EBoardKeyList } from "../Common/BoardKeyList"; import { observable } from "mobx"; +import { Hole } from "../DatabaseServices/3DSolid/Hole"; +import { GangDrillType, CylinderHole } from "../DatabaseServices/3DSolid/CylinderHole"; export interface DrillTypeCount { name: string; @@ -14,7 +15,7 @@ export interface DrillTypeCount } export class LookOverBoardInfos implements Command { - @observable private drillTypeMap: Map = new Map(); + @observable private drillTypeMap: Map = new Map(); async exec() { let enRes = await app.Editor.GetSelection({ @@ -29,7 +30,7 @@ export class LookOverBoardInfos implements Command let brsProps = enRes.SelectSet.SelectEntityList as Board[]; //计算排钻个数 - const addDrillToMap = (type: string, d: GangDrill) => + const addDrillToMap = (type: string, d: Hole) => { if (!this.drillTypeMap.has(type)) this.drillTypeMap.set(type, [d]); @@ -53,23 +54,28 @@ export class LookOverBoardInfos implements Command { for (let objId of ids) { - let gd = objId.Object as GangDrill; + let gd = objId.Object; if (!gd.IsErase) { - switch (gd.Type) + if (gd instanceof CylinderHole) + switch (gd.Type) + { + case GangDrillType.Ljg: + if (gd.MId && (!gd.MId.IsErase)) + { + let br = gd.MId.Object as Board; + let type = br.BoardProcessOption[EBoardKeyList.DrillType]; + //todo 需要读取拆单名 从userConfig中读取 如何判断在哪个距离区间 + addDrillToMap(type, gd); + } + break; + case GangDrillType.Wood: + addDrillToMap("木销", gd); + break; + } + else { - case GangDrillType.Ljg: - if (gd.MId && (!gd.MId.IsErase)) - { - let br = gd.MId.Object as Board; - let type = br.BoardProcessOption[EBoardKeyList.DrillType]; - //todo 需要读取拆单名 从userConfig中读取 如何判断在哪个距离区间 - addDrillToMap(type, gd); - } - break; - case GangDrillType.Wood: - addDrillToMap("木销", gd); - break; + //TODO:统计自定义排钻 } } } diff --git a/src/Add-on/Print.ts b/src/Add-on/Print.ts index b7e209b8c..b6cdf5ce8 100644 --- a/src/Add-on/Print.ts +++ b/src/Add-on/Print.ts @@ -2,7 +2,6 @@ import { Object3D, Scene, Vector3 } from "three"; import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer"; import { app } from "../ApplicationServices/Application"; import { Sleep } from "../Common/Sleep"; -import { GangDrill } from "../DatabaseServices/3DSolid/GangDrill"; import { CADFiler } from "../DatabaseServices/CADFiler"; import { AlignedDimension } from "../DatabaseServices/Dimension/AlignedDimension"; import { Board } from "../DatabaseServices/Entity/Board"; @@ -15,6 +14,7 @@ import { RenderType } from "../GraphicsSystem/RenderType"; import { AAType } from "../GraphicsSystem/Viewer"; import { HotCMD } from "../Hot/HotCommand"; import { DisposeThreeObj } from "../Common/Dispose"; +import { Hole } from "../DatabaseServices/3DSolid/Hole"; @HotCMD export class Print implements Command @@ -77,7 +77,7 @@ async function PrintImage(ens: Entity[]) //绘制 for (let e of ens) { - if (e instanceof GangDrill) continue; + if (e instanceof Hole) continue; if (e instanceof AlignedDimension) { e["OnlyRenderType"] = false; diff --git a/src/Add-on/RotateLayerBoard.ts b/src/Add-on/RotateLayerBoard.ts index 16284aa17..fef4ad250 100644 --- a/src/Add-on/RotateLayerBoard.ts +++ b/src/Add-on/RotateLayerBoard.ts @@ -6,7 +6,7 @@ import { PromptStatus } from "../Editor/PromptResult"; import { Board, BoardType } from "../DatabaseServices/Entity/Board"; import { Matrix4, Math as TMath, Vector3 } from "three"; import { MoveMatrix, isParallelTo, equaln } from "../Geometry/GeUtils"; -import { GangDrill } from "../DatabaseServices/3DSolid/GangDrill"; +import { CylinderHole } from "../DatabaseServices/3DSolid/CylinderHole"; import { DrawDrillingTool } from "./DrawDrilling/DrawDrillingTool"; import { arrayLast } from "../Common/ArrayExt"; import { AppToaster } from "../UI/Components/Toaster"; @@ -133,11 +133,9 @@ export class RotateLayerBoard implements Command { this.currentBoard.Width = newWidth; this.currentBoard.ApplyMatrix(oldBrData.diffMat); - //修正排钻 - this.RotateDrillList(); } /** - * 重新计算层板钉 + * 重新计算层板钉 * newTotalWidth-总宽 */ private RotateNails(angle: number, newTotalWidth: number, oldBrData: IOldBrData) @@ -153,10 +151,10 @@ export class RotateLayerBoard implements Command this.RotateLeftRightNails(rightNails, singleDist, oldBrData, -angle); } /** - * 旋转修正背板的层板钉 + * 旋转修正背板的层板钉 * totalWidth-用于计算的总宽 * */ - private RotateBackNails(backNails: GangDrill[], angle: number, totalWidth: number, oldBrData: IOldBrData) + private RotateBackNails(backNails: CylinderHole[], angle: number, totalWidth: number, oldBrData: IOldBrData) { let tanAng = Math.tan(Math.abs(angle)); let sinAng = Math.sin(Math.abs(angle)); @@ -186,11 +184,11 @@ export class RotateLayerBoard implements Command } } /**旋转修正左右板的层板钉 */ - private RotateLeftRightNails(nails: GangDrill[], singleDist: number, oldBrData: IOldBrData, angle: number) + private RotateLeftRightNails(nails: CylinderHole[], singleDist: number, oldBrData: IOldBrData, angle: number) { let pos: Vector3; let refIndex: number; - let nailMap: Map = new Map(); + let nailMap: Map = new Map(); let ocsInv = new Matrix4().getInverse(oldBrData.OCS); for (let i = 0; i < nails.length; i++) @@ -240,7 +238,7 @@ export class RotateLayerBoard implements Command } } /*旧版CAD层板钉排列规则 */ - private RotateLeftRightNails2(nails: GangDrill[], oldBrData: IOldBrData, angle: number) + private RotateLeftRightNails2(nails: CylinderHole[], oldBrData: IOldBrData, angle: number) { let distMap: Map = new Map(); let ocsInv = new Matrix4().getInverse(oldBrData.OCS); @@ -294,15 +292,15 @@ export class RotateLayerBoard implements Command private ParseNails(oldBrData: IOldBrData) { let nails = this.currentBoard.LayerNails; - let backNails: GangDrill[] = []; - let leftNails: GangDrill[] = []; - let rightNails: GangDrill[] = []; + let backNails: CylinderHole[] = []; + let leftNails: CylinderHole[] = []; + let rightNails: CylinderHole[] = []; let brX = new Vector3().setFromMatrixColumn(oldBrData.OCS, 0); let brY = new Vector3().setFromMatrixColumn(oldBrData.OCS, 1); for (let nid of nails) { - let nail = nid.Object as GangDrill; + let nail = nid.Object as CylinderHole; if (nail) { //层板钉法向量和层板Y轴方向平行,为背板上得层板钉 @@ -360,29 +358,4 @@ export class RotateLayerBoard implements Command frontDist, backDist, count, backNails, leftNails, rightNails }; } - /**重新计算排钻 */ - private RotateDrillList() - { - let drills = this.currentBoard.DrillList; - let needCalcBr: Board[] = [this.currentBoard]; - - let brY = new Vector3().setFromMatrixColumn(this.currentBoard.OCS, 1); - - for (let [brId, ids] of drills) - { - let b = brId.Object as Board; - if (!b || ids.length === 0) continue; - let firstD = ids[0][1].Object as GangDrill; - //当目标板为背板或者立板得排钻连接杆法向量和层板y轴不平行,或者都是层板法向量不平行,直接清理掉排钻 - let isClear = b.BoardType === BoardType.Behind || - (b.BoardType === BoardType.Vertical && !isParallelTo(firstD.Normal, brY)) || - (b.BoardType === BoardType.Layer && !isParallelTo(b.Normal, this.currentBoard.Normal)); - - if (isClear) - this.currentBoard.ClearDrillList(brId); - else - needCalcBr.push(b); - } - (DrawDrillingTool.GetInstance() as DrawDrillingTool).StartGangDrill(needCalcBr); - } } diff --git a/src/Add-on/testEntity/test.ts b/src/Add-on/testEntity/test.ts index 9d1c1263f..51ae5b102 100644 --- a/src/Add-on/testEntity/test.ts +++ b/src/Add-on/testEntity/test.ts @@ -19,12 +19,13 @@ export class Test implements Command if (enRes.Status === PromptStatus.OK) { - let en = enRes.SelectSet.SelectEntityList as Board[]; + let en = enRes.SelectSet.SelectEntityList; for (let e of en) { // if (e.IsClockWise) e.ColorIndex = 1; - console.log(Production.GetBoardSplitOrderData(e as Board)); + if (e instanceof Board) + console.log(Production.GetBoardSplitOrderData(e)); } } } diff --git a/src/Add-on/testEntity/testCollision.ts b/src/Add-on/testEntity/testCollision.ts index de1ac1bc6..0e7bcfb64 100644 --- a/src/Add-on/testEntity/testCollision.ts +++ b/src/Add-on/testEntity/testCollision.ts @@ -24,16 +24,16 @@ export class TestCollision implements Command { let checkRes = new CollisionDetection(boardCus); - for (let f of checkRes.m_CollisonFaces) + for (let f of checkRes.CollisonFaces) { showFace(f); } } else { - for (let bf of checkRes.m_BoardGeList) + for (let bf of checkRes.BoardGeList) { - for (let f of bf.m_Faces) + for (let f of bf.Faces) { if (f.type !== BoardFaceType.Side) showFace(f); diff --git a/src/Common/AppCache.ts b/src/Common/AppCache.ts index 9ab4d4ada..c0adee72f 100644 --- a/src/Common/AppCache.ts +++ b/src/Common/AppCache.ts @@ -16,6 +16,9 @@ class Appcache return val; if (val instanceof CADObject) return val.Clone(); + if (Array.isArray(val) && val[0] instanceof CADObject) + return val.slice(); + return JSON.parse(JSON.stringify(val)); } set(key: string, value: T) @@ -26,6 +29,10 @@ class Appcache { this._cacheMap.clear(); } + delete(k: string) + { + this._cacheMap.delete(k); + } } export const appCache = new Appcache(); diff --git a/src/Common/Request.ts b/src/Common/Request.ts index 312667d47..98336a222 100644 --- a/src/Common/Request.ts +++ b/src/Common/Request.ts @@ -13,6 +13,7 @@ export enum DirectoryId ImgDir = "3", //图片根目录 ToplineDir = "4", //材质根目录 TemplateDir = "5", //材质根目录 + DrillingDir = "6", //排钻目录 } export enum RequestStatus diff --git a/src/Common/SerializeMaterial.ts b/src/Common/SerializeMaterial.ts index b9d266927..3634be9e3 100644 --- a/src/Common/SerializeMaterial.ts +++ b/src/Common/SerializeMaterial.ts @@ -1,4 +1,4 @@ -import { Matrix4, Vector2, Vector3, Box3 } from "three"; +import { Matrix4, Vector2, Vector3, Box3, Scene } from "three"; import { app } from "../ApplicationServices/Application"; import { CADFiler } from "../DatabaseServices/CADFiler"; import { Database } from "../DatabaseServices/Database"; @@ -9,6 +9,11 @@ import { DuplicateRecordCloning } from "./Status"; import pako from "pako"; import { TemplateRecord } from "../DatabaseServices/Template/TemplateRecord"; import { TemplateParam } from "../DatabaseServices/Template/Param/TemplateParam"; +import { Entity } from "../DatabaseServices/Entity/Entity"; +import { AAType } from "../GraphicsSystem/Viewer"; +import { DisposeThreeObj } from "./Dispose"; +import { uploadLogo } from "./Request"; +import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole"; export function MaterialOut(material: PhysicalMaterialRecord): string { @@ -179,3 +184,47 @@ export function GetCurrentViewPreViewImage(restore = true): Blob } return dataURItoBlob(url); } + +export function ExtrudeDrillFileIn(data: any[]) +{ + let f = new CADFiler(data); + let en = new ExtrudeHole(); + en.ReadFile(f); + return en; +} + +export async function GetEntitysLogo(ens: Entity[]) +{ + //备份视图 + let sceneBak = app.Viewer.Scene; + + let aabak = app.Viewer.AAType; + let f = new CADFiler(); + app.Viewer.CameraCtrl.WriteFile(f); + + //设置视图 + app.Viewer.Scene = new Scene(); + app.Viewer._AAType = AAType.SMAA; + app.Viewer.CameraCtrl.LookAt(new Vector3(1, 1, -1)); + + //绘制 + for (let e of ens) + app.Viewer.Scene.add(e.DrawObject); + app.Viewer.ZoomAll(false); + let blob = GetCurrentViewPreViewImage(false); + + //还原视图 + [app.Viewer.Scene, sceneBak] = [sceneBak, app.Viewer.Scene]; + + app.Viewer._AAType = aabak; + f.Reset(); + app.Viewer.CameraCtrl.ReadFile(f); + app.Viewer.OnSize(); + + DisposeThreeObj(sceneBak); + + //上传 + let logo = await uploadLogo(blob); + + return logo; +} diff --git a/src/Common/StoreageKeys.ts b/src/Common/StoreageKeys.ts index afdc554bd..79081fcda 100644 --- a/src/Common/StoreageKeys.ts +++ b/src/Common/StoreageKeys.ts @@ -11,4 +11,6 @@ export enum StoreageKeys LastOpenFileId = "lastfid", Uid = "uid", Goods = "Goods_", + DrillTemp = "drilltemp_", + DrillReactor = "drillRreactor", } diff --git a/src/DatabaseServices/3DSolid/GangDrill.ts b/src/DatabaseServices/3DSolid/CylinderHole.ts similarity index 74% rename from src/DatabaseServices/3DSolid/GangDrill.ts rename to src/DatabaseServices/3DSolid/CylinderHole.ts index fc968e0a0..b226260c0 100644 --- a/src/DatabaseServices/3DSolid/GangDrill.ts +++ b/src/DatabaseServices/3DSolid/CylinderHole.ts @@ -1,16 +1,13 @@ -import { Box3, BufferGeometry, CylinderBufferGeometry, Float32BufferAttribute, LineSegments, Material, Matrix3, Matrix4, Mesh, Object3D, Shape as TShape, Vector3 } from "three"; +import { Box3, BufferGeometry, CylinderBufferGeometry, Float32BufferAttribute, LineSegments, Matrix4, Mesh, Object3D, Shape as TShape, Vector3, Matrix3 } from "three"; import { ColorMaterial } from '../../Common/ColorPalette'; import { DisposeThreeObj } from '../../Common/Dispose'; import { FixIndex } from "../../Common/Utils"; -import { ObjectSnapMode } from "../../Editor/ObjectSnapMode"; import { RenderType } from "../../GraphicsSystem/RenderType"; -import { AutoRecord } from "../AutoRecord"; -import { Factory } from '../CADFactory'; +import { Factory, CADFactory } from '../CADFactory'; import { CADFiler } from '../CADFiler'; -import { Circle } from '../Entity/Circle'; -import { ObjectId } from '../ObjectId'; -import { Shape } from '../Shape'; -import { Solid3D } from "./Solid3D"; +import { Hole } from "./Hole"; +import { ObjectSnapMode } from "../../Editor/ObjectSnapMode"; +import { Circle } from "../Entity/Circle"; export enum GangDrillType { @@ -26,7 +23,6 @@ export enum GangDrillType Wood = 4, /** 通孔 */ TK = 5, - /**木销定位大孔 */ WoodPXL = 6, } @@ -34,23 +30,20 @@ let TempCircle1 = new Circle(); let TempCircle2 = new Circle(); @Factory -export class GangDrill extends Solid3D +export class CylinderHole extends Hole { - private _Height: number; - private _Radius: number; + private _Radius: number = 1; private type: GangDrillType = GangDrillType.Pxl; - @AutoRecord FId: ObjectId; - @AutoRecord MId: ObjectId; constructor() { super(); this._Color = 1; } - static CreateCylDrill(rad: number, height: number, type: GangDrillType) + static CreateCylHole(radius: number, height: number, type: GangDrillType) { - let drill = new GangDrill(); - drill._Height = height; - drill._Radius = rad; + let drill = new CylinderHole(); + drill.Height = height; + drill._Radius = radius; drill.type = type; return drill; } @@ -60,35 +53,37 @@ export class GangDrill extends Solid3D } set Type(t: GangDrillType) { - this.WriteAllObjectRecord(); - this.type = t; - } - get Height() - { - return this._Height; - } - set Height(v: number) - { - if (this._Height !== v) + if (this.type !== t) { this.WriteAllObjectRecord(); - this._EdgeGeometry = null; - this._MeshGeometry = null; - this._Height = v; - this.Update(); + this.type = t; } } + set Radius(r: number) { - if (this._Radius !== r) + if (r !== this._Radius) { this.WriteAllObjectRecord(); - this._EdgeGeometry = null; this._MeshGeometry = null; + this._EdgeGeometry = null; this._Radius = r; this.Update(); } } + get Height() + { + return super.Height; + } + set Height(v: number) + { + if (this._Height !== v) + { + this._MeshGeometry = null; + this._EdgeGeometry = null; + super.Height = v; + } + } get Radius() { return this._Radius; @@ -98,10 +93,6 @@ export class GangDrill extends Solid3D let box = new Box3(new Vector3(-this._Radius, -this._Radius, 0), new Vector3(this._Radius, this._Radius, this._Height)); return box.applyMatrix4(this.OCS); } - Collise(tarDrill: GangDrill): boolean - { - return this.BoundingBox.intersectsBox(tarDrill.BoundingBox); - } private _MeshGeometry: CylinderBufferGeometry; private get MeshGeometry() { @@ -120,7 +111,13 @@ export class GangDrill extends Solid3D this._EdgeGeometry = FastDrillingEdgeGeometry(this._Radius, this.Height); return this._EdgeGeometry; } - + GetGripPoints() + { + let cir = new Circle(new Vector3(), this._Radius); + let pts = cir.GetGripPoints(); + pts.push(...pts.map(p => p.clone().add(new Vector3(0, 0, this.Height)))); + return pts.map(p => p.applyMatrix4(this.OCS)); + } GetObjectSnapPoints( snapMode: ObjectSnapMode, pickPoint: Vector3, @@ -141,7 +138,6 @@ export class GangDrill extends Solid3D } return pts; } - InitDrawObject(renderType: RenderType) { return this.GetObject3DByRenderType(renderType); @@ -158,43 +154,31 @@ export class GangDrill extends Solid3D DisposeThreeObj(obj); obj.add(this.GetObject3DByRenderType(type)); } - UpdateDrawObjectMaterial(type: RenderType, obj: Object3D, material?: Material) - { - let m = obj as LineSegments; - m.material = material || ColorMaterial.GetLineMaterial(this.ColorIndex); - } + protected _ReadFile(file: CADFiler) { super._ReadFile(file); let ver = file.Read();//1 - if (ver <= 3) + this._Radius = file.Read(); + if (ver <= 4) { - let shape = new Shape(); - shape.ReadFile(file); - this._Radius = ((shape.Outline.Curve)).Radius; - } - else - this._Radius = file.Read(); - this._Height = file.Read(); - - this.type = GangDrillType.Pxl; - if (ver >= 2) + //临时兼容旧排钻 + this._Height = file.Read(); this.type = file.Read(); - if (ver >= 3) - { this.FId = file.ReadSoftObjectId(); this.MId = file.ReadSoftObjectId(); } + else + { + this.type = file.Read(); + } } WriteFile(file: CADFiler) { super.WriteFile(file); - file.Write(4);//ver + file.Write(5);//ver file.Write(this._Radius); - file.Write(this._Height); file.Write(this.type); - file.WriteSoftObjectId(this.FId); - file.WriteSoftObjectId(this.MId); } } @@ -235,7 +219,9 @@ export function FastDrillingEdgeGeometry(radius: number, height: number): Buffer coords.push(p.x, p.y, 0, p.x, p.y, height);//edge } - geo.setAttribute('position', new Float32BufferAttribute(coords, 3)); + geo.addAttribute('position', new Float32BufferAttribute(coords, 3)); cache2.set(key, geo); return geo; } + +CADFactory.RegisterObjectAlias(CylinderHole, "GangDrill"); diff --git a/src/DatabaseServices/3DSolid/Cylineder.ts b/src/DatabaseServices/3DSolid/Cylineder.ts index ea68a1c8e..7f4ce06dc 100644 --- a/src/DatabaseServices/3DSolid/Cylineder.ts +++ b/src/DatabaseServices/3DSolid/Cylineder.ts @@ -2,13 +2,13 @@ import * as THREE from 'three'; import { MeshNormalMaterial, Object3D, Geometry, Vector3, ExtrudeGeometry } from "three"; import { RenderType } from "../../GraphicsSystem/RenderType"; import { CADFiler } from '../CADFiler'; -import { Solid3D } from "./Solid3D"; import { Factory } from '../CADFactory'; import { Contour } from '../Contour'; import { Circle } from '../Entity/Circle'; +import { Entity } from '../Entity/Entity'; @Factory -export class Cylineder extends Solid3D +export class Cylineder extends Entity { private m_Radius: number; private m_Height: number; diff --git a/src/DatabaseServices/3DSolid/ExtrudeHole.ts b/src/DatabaseServices/3DSolid/ExtrudeHole.ts new file mode 100644 index 000000000..b3a7a37c1 --- /dev/null +++ b/src/DatabaseServices/3DSolid/ExtrudeHole.ts @@ -0,0 +1,354 @@ +import { BufferGeometry, ExtrudeGeometry, ExtrudeGeometryOptions, Geometry, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Vector3 } from "three"; +import { arrayClone, arrayLast, arraySortByNumber } from "../../Common/ArrayExt"; +import { ColorMaterial } from "../../Common/ColorPalette"; +import { DisposeThreeObj } from "../../Common/Dispose"; +import { Vector2ApplyMatrix4 } from "../../Common/Matrix4Utils"; +import { ObjectSnapMode } from "../../Editor/ObjectSnapMode"; +import { FastWireframe2 } from "../../Geometry/CreateWireframe"; +import { EdgesGeometry } from "../../Geometry/EdgeGeometry"; +import { equaln, equalv2, equalv3, ZeroVec } from "../../Geometry/GeUtils"; +import { RenderType } from "../../GraphicsSystem/RenderType"; +import { Factory } from "../CADFactory"; +import { CADFiler } from "../CADFiler"; +import { Contour } from "../Contour"; +import { DragPointType } from "../Entity/DragPointType"; +import { ExtureContourCurve } from "../Entity/Extrude"; +import { Polyline } from "../Entity/Polyline"; +import { Shape } from "../Shape"; +import { Hole } from "./Hole"; + +@Factory +export class ExtrudeHole extends Hole +{ + private _contourCurve: ExtureContourCurve = new Polyline(); + private _EdgeGeometry: EdgesGeometry; + protected _knifeRadius: number = 3; + get KnifeRadius() + { + return this._knifeRadius; + } + set KnifeRadius(v: number) + { + if (!equaln(v, this._knifeRadius)) + { + this.WriteAllObjectRecord(); + this._knifeRadius = v; + } + } + get ContourCurve() + { + return this._contourCurve; + } + + set ContourCurve(curve: ExtureContourCurve) + { + if (!curve.IsClose) return; + + if (curve instanceof Polyline) + { + curve.CloseMark = true; + let pts = curve.LineData; + if (equalv2(pts[0].pt, arrayLast(pts).pt)) + pts.pop(); + + //如果曲线被旋转了,那么修正它的旋转矩阵,避免纹路错误 + let ocs = curve.OCS; + if (!equaln(ocs.elements[0], 1))// || ocs.elements[9] || ocs.elements[10] + { + for (let p of pts) + Vector2ApplyMatrix4(ocs, p.pt); + curve.OCS = new Matrix4(); + } + curve.ClearDraw(); + } + + this.WriteAllObjectRecord(); + this._contourCurve = curve; + this.CheckContourCurve(); + this.Update(); + } + CheckContourCurve() + { + let box = this._contourCurve.BoundingBox; + + //修正轮廓基点 + if (!equalv3(box.min, ZeroVec)) + { + this._contourCurve.Position = + this._contourCurve.Position.sub(box.min); + + let v = box.min.applyMatrix4(this.OCS.setPosition(ZeroVec)); + this._Matrix.setPosition(this.Position.add(v)); + } + } + GetObjectSnapPoints( + snapMode: ObjectSnapMode, + pickPoint: Vector3, + lastPoint: Vector3, + viewXform?: Matrix3 + ): Vector3[] + { + switch (snapMode) + { + case ObjectSnapMode.End: + return this.GetStretchPoints(); + case ObjectSnapMode.Mid: + case ObjectSnapMode.Cen: + case ObjectSnapMode.Nea: + case ObjectSnapMode.Ext: + case ObjectSnapMode.Per: + case ObjectSnapMode.Tan: + { + let contour = this.ContourCurve.Clone(); + contour.ApplyMatrix(this.OCS); + let pts = contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform); + + contour.Position = contour.Position.add(this.Normal.multiplyScalar(this.Height)); + pts.push( + ...contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform) + ); + return pts; + } + default: + break; + } + return []; + } + get Shape() + { + let contour = Contour.CreateContour(this.ContourCurve.Clone(), false); + + return new Shape(contour); + } + get BoundingBoxInOCS() + { + let box = this.ContourCurve.BoundingBox; + box.max.add(new Vector3(0, 0, this.Height)); + return box; + } + get BoundingBox() + { + let box = this.ContourCurve.BoundingBox; + box.max.add(new Vector3(0, 0, this.Height)); + box.applyMatrix4(this.OCS); + return box; + } + private get EdgeGeometry() + { + if (this._EdgeGeometry) + return this._EdgeGeometry; + + this._EdgeGeometry = new EdgesGeometry().FromGeometry(this.MeshGeometry); + return this._EdgeGeometry; + } + private _MeshGeometry: BufferGeometry | Geometry; + private get MeshGeometry() + { + if (this._MeshGeometry) + return this._MeshGeometry; + + this._MeshGeometry = this.GeneralMeshGeometry(); + return this._MeshGeometry; + } + private GeneralMeshGeometry() + { + let extrudeSettings: ExtrudeGeometryOptions = { + steps: 1, + bevelEnabled: false, + depth: this.Height, + }; + let geo = new ExtrudeGeometry(this.ContourCurve.Shape, extrudeSettings); + geo.applyMatrix(this._contourCurve.OCS); + return geo; + } + GetGripOrStretchPoints(dragType: DragPointType) + { + let isGrip = dragType === DragPointType.Grip; + + let pts = isGrip ? this.ContourCurve.GetGripPoints() : this.ContourCurve.GetStretchPoints(); + let v = new Vector3(0, 0, this.Height); + pts.push(...pts.map(p => p.clone().add(v))); + pts.forEach(p => { p.applyMatrix4(this.OCS) }); + + return pts; + } + private GetStrectchPointCountList(dragType: DragPointType): number + { + return this.ContourCurve.GetDragPointCount(dragType) * 2; + } + MoveGripOrStretchPoints(indexList: number[], vec: Vector3, dragType: DragPointType) + { + this.WriteAllObjectRecord(); + if (dragType === DragPointType.Stretch && indexList.length === this.GetStrectchPointCountList(dragType)) + { + this.Position = this.Position.add(vec); + return; + } + arraySortByNumber(indexList); + this.MoveGripOrStretchPointsOnly(indexList, vec, dragType); + this.CheckContourCurve(); + this.Update(); + } + IsStretchHeight(indexs: number[]) + { + let count = this.ContourCurve.GetStretchPoints().length; + if (indexs.length === count) + { + let isF = indexs[0] < count; + return indexs.every(i => isF === (i < count)); + } + return false; + } + MoveGripOrStretchPointsOnly(indexList: Array, vec: Vector3, dragType: DragPointType) + { + let stretchCount = this.ContourCurve.GetDragPointCount(dragType); + + if (dragType === DragPointType.Stretch) + { + //Move + if (indexList.length === stretchCount * 2) + { + this.Position = this.Position.add(vec); + return; + } + + //判断是否拉伸厚度 + if (this.IsStretchHeight(indexList)) + { + let isFront = indexList[0] < stretchCount; + + if (indexList.every(v => v < stretchCount === isFront)) + { + //Change thickness + let lvec = vec.clone().applyMatrix4(this.OCSInv.setPosition(ZeroVec)); + if (isFront) + { + this.Height -= lvec.z; + //移动位置而不改变内部拉槽 + let v = this.Normal.multiplyScalar(lvec.z); + this._Matrix.elements[12] += v.x; + this._Matrix.elements[13] += v.y; + this._Matrix.elements[14] += v.z; + } + else + { + this.Height += lvec.z; + } + return; + } + } + + indexList = arrayClone(indexList); + } + + //修正点的索引 + for (let i = 0; i < indexList.length; i++) + { + let index = indexList[i]; + if (index >= stretchCount) + { + index -= stretchCount; + indexList[i] = index; + } + } + + indexList = [...new Set(indexList)]; + + let localVec = vec.clone().applyMatrix4(this.OCSInv.setPosition(ZeroVec)); + + if (dragType === DragPointType.Grip) + { + if (this.ContourCurve instanceof Polyline + && indexList.length === 1 + && indexList[0] % 2 === 1) + { + let param = indexList[0] / 2; + if (this.ContourCurve.GetBuilgeAt(Math.floor(param)) === 0) + { + let der = this.ContourCurve.GetFistDeriv(param).normalize(); + [der.x, der.y] = [der.y, -der.x]; + let d = localVec.dot(der); + localVec.copy(der).multiplyScalar(d); + } + } + this.ContourCurve.MoveGripPoints(indexList, localVec); + } + else + this.ContourCurve.MoveStretchPoints(indexList, localVec); + } + GetGripPoints(): Array + { + return this.GetGripOrStretchPoints(DragPointType.Grip); + } + GetStretchPoints() + { + return this.GetGripOrStretchPoints(DragPointType.Stretch); + } + MoveGripPoints(indexList: number[], vec: Vector3) + { + this.MoveGripOrStretchPoints(indexList, vec, DragPointType.Grip) + } + MoveStretchPoints(indexList: Array, vec: Vector3) + { + this.MoveGripOrStretchPoints(indexList, vec, DragPointType.Stretch); + } + InitDrawObject(renderType: RenderType = RenderType.Wireframe) + { + if (renderType === RenderType.Wireframe) + { + return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)) + } + else if (renderType === RenderType.Conceptual || renderType === RenderType.Physical) + { + return new Object3D().add( + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)), + new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(7)) + ); + } + else if (renderType === RenderType.Jig) + { + return new Object3D().add(...FastWireframe2(this)); + } + } + UpdateDrawObject(renderType: RenderType, obj: Object3D) + { + DisposeThreeObj(obj); + this._EdgeGeometry = undefined; + this._MeshGeometry = undefined; + this.MeshGeometry; + + if (renderType === RenderType.Wireframe) + { + let l = obj as LineSegments; + l.geometry = this.EdgeGeometry; + l.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + } + else if (renderType === RenderType.Conceptual || renderType === RenderType.Physical) + { + return obj.add( + new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)), + new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(7)) + ); + } + else if (renderType === RenderType.Jig) + { + obj.add(...FastWireframe2(this)); + } + } + ReadFile(file: CADFiler) + { + super.ReadFile(file); + let ver = file.Read(); + this._contourCurve = file.ReadObject() as ExtureContourCurve; + this._knifeRadius = file.Read(); + this.Update(); + } + //对象将自身数据写入到文件. + WriteFile(file: CADFiler) + { + super.WriteFile(file); + file.Write(1); + file.WriteObject(this._contourCurve); + file.Write(this._knifeRadius); + } +} diff --git a/src/DatabaseServices/3DSolid/Hole.ts b/src/DatabaseServices/3DSolid/Hole.ts new file mode 100644 index 000000000..76fcc0106 --- /dev/null +++ b/src/DatabaseServices/3DSolid/Hole.ts @@ -0,0 +1,51 @@ +import { Factory } from '../CADFactory'; +import { Entity } from '../Entity/Entity'; +import { AutoRecord } from '../AutoRecord'; +import { ObjectId } from '../ObjectId'; +import { CADFiler } from '../CADFiler'; + +@Factory +export class Hole extends Entity +{ + @AutoRecord FId: ObjectId; + @AutoRecord MId: ObjectId; + protected _Height: number; + get Height() + { + return this._Height; + } + set Height(v: number) + { + if (this._Height !== v) + { + this.WriteAllObjectRecord(); + this._Height = v; + this.Update(); + } + } + protected _ReadFile(file: CADFiler) + { + super._ReadFile(file); + let ver = file.Read();//1 + if (ver <= 4) + { + //临时兼容旧图纸排钻,更新旧图纸后去掉兼容代码 + file['readIndex']--; + } + else + { + this._Height = file.Read(); + this.FId = file.ReadSoftObjectId(); + this.MId = file.ReadSoftObjectId(); + } + + } + WriteFile(file: CADFiler) + { + super.WriteFile(file); + file.Write(5);//ver + file.Write(this._Height); + file.WriteSoftObjectId(this.FId); + file.WriteSoftObjectId(this.MId); + } +} diff --git a/src/DatabaseServices/3DSolid/Solid3D.ts b/src/DatabaseServices/3DSolid/Solid3D.ts deleted file mode 100644 index afa8c33e6..000000000 --- a/src/DatabaseServices/3DSolid/Solid3D.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Factory } from '../CADFactory'; -import { Entity } from '../Entity/Entity'; - -@Factory -export class Solid3D extends Entity -{ -} diff --git a/src/DatabaseServices/3DSolid/SweepSolid.ts b/src/DatabaseServices/3DSolid/SweepSolid.ts index 5f153c3b3..f92752789 100644 --- a/src/DatabaseServices/3DSolid/SweepSolid.ts +++ b/src/DatabaseServices/3DSolid/SweepSolid.ts @@ -11,10 +11,10 @@ import { Curve } from "../Entity/Curve"; import { PhysicalMaterialRecord } from '../PhysicalMaterialRecord'; import { IsPointInPolyLine } from '../PointInPolyline'; import { Polyline } from '../Entity/Polyline'; -import { Solid3D } from "./Solid3D"; +import { Entity } from "../Entity/Entity"; @Factory -export class SweepSolid extends Solid3D +export class SweepSolid extends Entity { private _Contour: Polyline; private _PathCurve: Curve; diff --git a/src/DatabaseServices/Entity/Board.ts b/src/DatabaseServices/Entity/Board.ts index de69a0bcb..e4a501349 100644 --- a/src/DatabaseServices/Entity/Board.ts +++ b/src/DatabaseServices/Entity/Board.ts @@ -479,23 +479,12 @@ export class Board extends ExtrudeSolid this.WriteAllObjectRecord(); this._SpecOCS.copy(m); } - get BoundingBox() - { - let box = new Box3Ext(new Vector3(0, 0, 0), new Vector3(this.width, this.height, this.thickness)); - box.applyMatrix4(this.OCS); - return box; - } - // get Shape() - // { - // return this.ContourCurve; - // } - // set Shape(s: Shape) - // { - // this.WriteAllObjectRecord(); - // // this.m_Shape = s; - // this.UpdateBoardSize(); - // this.Update(); - // } + + get IsRect() + { + return this.isRect; + } + get IsSpecialShape() { return !this.isRect; diff --git a/src/DatabaseServices/Entity/Extrude.ts b/src/DatabaseServices/Entity/Extrude.ts index 51e0d6194..43071aee8 100644 --- a/src/DatabaseServices/Entity/Extrude.ts +++ b/src/DatabaseServices/Entity/Extrude.ts @@ -94,7 +94,10 @@ export class ExtrudeSolid extends Entity this.knifeRadius = v; } } - + get BoundingBox() + { + return this.BoundingBoxInOCS.applyMatrix4(this.OCS); + } get BoundingBoxInOCS(): Box3Ext { return new Box3Ext(new Vector3(), new Vector3(this.width, this.height, this.thickness)); diff --git a/src/DatabaseServices/Shape.ts b/src/DatabaseServices/Shape.ts index 9264d794b..178a594e4 100644 --- a/src/DatabaseServices/Shape.ts +++ b/src/DatabaseServices/Shape.ts @@ -51,7 +51,17 @@ export class Shape this.UpdateShape(); return this.m_Shape; } - + get Position() + { + return this.m_Outline.Curve.Position; + } + set Position(p: Vector3) + { + let vec = p.clone().sub(this.m_Outline.Curve.Position); + this.m_Outline.Curve.Position = p; + for (let h of this.m_Holes) + h.Curve.Position = h.Curve.Position.add(vec); + } Z0() { this.m_Outline.Curve.Z0(); diff --git a/src/Editor/CommandRegister.ts b/src/Editor/CommandRegister.ts index 5ea93f3f4..b43257998 100644 --- a/src/Editor/CommandRegister.ts +++ b/src/Editor/CommandRegister.ts @@ -142,6 +142,8 @@ import { commandMachine } from './CommandMachine'; import { EditorLattice } from "../Add-on/LatticeDrawer/EditorLattice"; import { Print } from "../Add-on/Print"; import { AutoHoleFaceSetting } from "../Add-on/AutoHoleFaceSetting"; +import { DrawExtrude } from "../Add-on/DrawExtrude"; +import { ShowDrillingTemplate } from "../Add-on/DrawDrilling/ShowDrillingTemplate"; export function registerCommand() { @@ -384,6 +386,9 @@ export function registerCommand() commandMachine.RegisterCommand("testPl2Pts", new Command_Polyline2Path()); commandMachine.RegisterCommand("editorlattice", new EditorLattice()); commandMachine.RegisterCommand("print", new Print()); + commandMachine.RegisterCommand("extrude", new DrawExtrude()); + + commandMachine.RegisterCommand("drilltemplate", new ShowDrillingTemplate()); RegistCustomCommand(); } diff --git a/src/Editor/UserConfig.ts b/src/Editor/UserConfig.ts index eaff2c1c6..961f5b303 100644 --- a/src/Editor/UserConfig.ts +++ b/src/Editor/UserConfig.ts @@ -32,6 +32,8 @@ export class UserConfig let type = localStorage.getItem(StoreageKeys.RenderType); if (type) this._renderType = parseFloat(type); + + this.openDrillingReactor = !!localStorage.getItem(StoreageKeys.DrillReactor); } set RenderType(t: RenderType) { diff --git a/src/Geometry/CreateWireframe.ts b/src/Geometry/CreateWireframe.ts index 9a4f3ab51..5bf1c143d 100644 --- a/src/Geometry/CreateWireframe.ts +++ b/src/Geometry/CreateWireframe.ts @@ -8,6 +8,7 @@ import { ExtrudeSolid } from "../DatabaseServices/Entity/Extrude"; import { Shape } from "../DatabaseServices/Shape"; import { FaceDirection } from "../UI/Store/BoardInterface"; import { MoveMatrix } from "./GeUtils"; +import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole"; //FIXME: #IWBPB 性能缺陷和BUG. 等待废弃或者改进 export function CreateWireframe(en3D: Board | ExtrudeSolid) @@ -141,3 +142,40 @@ export function FastWireframe(br: ExtrudeSolid, color = 0) return result; } +export function FastWireframe2(dr: ExtrudeHole, color = 0) +{ + color = color || dr.ColorIndex; + let material = ColorMaterial.GetLineMaterial(color); + + let height = dr.Height; + + let cu = dr.ContourCurve; + let pts = cu.Shape.getPoints(6); + + let geo = new BufferGeometry(); + let coords: number[] = []; + let edgeCoords: number[] = []; + + for (let p of pts) + { + coords.push(p.x, p.y, 0); + if (p["_mask_"]) + edgeCoords.push(p.x, p.y, 0, p.x, p.y, height); + } + for (let p of pts) + coords.push(p.x, p.y, height); + + let edgeGeo = new BufferGeometry(); + edgeGeo.addAttribute('position', new Float32BufferAttribute(edgeCoords, 3)); + geo.addAttribute('position', new Float32BufferAttribute(coords, 3)); + + let line = new Line(geo, material); + line.applyMatrix(cu.OCS); + + let edge = new LineSegments(edgeGeo, material) + edge.applyMatrix(cu.OCS); + + let result = [line, edge]; + + return result; +} diff --git a/src/Geometry/DrillParse/BoardGetFace.ts b/src/Geometry/DrillParse/BoardGetFace.ts index f508cdad3..d0c09b6ae 100644 --- a/src/Geometry/DrillParse/BoardGetFace.ts +++ b/src/Geometry/DrillParse/BoardGetFace.ts @@ -5,7 +5,7 @@ import { Board } from "../../DatabaseServices/Entity/Board"; import { Curve } from "../../DatabaseServices/Entity/Curve"; import { Region } from "../../DatabaseServices/Entity/Region"; import { DrillType } from "../../UI/Store/BoardInterface"; -import { equaln, equalv3, rotatePoint, ZAxis } from "../GeUtils"; +import { equaln, equalv3, ZAxis } from "../GeUtils"; import { Face } from "./Face"; export enum BoardFaceType @@ -15,11 +15,9 @@ export enum BoardFaceType } export class BoardGetFace { - m_Board: Board; - m_Faces: Face[] = []; - constructor(br: Board) + Faces: Face[] = []; + constructor(public Board: Board) { - this.m_Board = br; this.ParseFaces(); } ParseFaces() @@ -31,56 +29,51 @@ export class BoardGetFace } GetTopAndBottomFace() { - let curve = this.m_Board.ContourCurve; - - let box = curve.BoundingBox; - let size = box.getSize(new Vector3()); - + let curve = this.Board.ContourCurve; let reg: Region; - let isRect = !this.m_Board.IsSpecialShape; - if (!isRect) + if (this.Board.IsSpecialShape) reg = Region.CreateFromCurves([curve]); - let thickness = this.m_Board.Thickness; - let ocs = this.m_Board.OCS; - const opt = this.m_Board.BoardProcessOption; + let thickness = this.Board.Thickness; + let ocs = this.Board.OCS; + const opt = this.Board.BoardProcessOption; //正反面 if (opt.frontDrill) - this.m_Faces.push(new Face({ + this.Faces.push(new Face({ type: BoardFaceType.NoSide, region: reg, - isRect, - localBoard: this.m_Board, + isRect: this.Board.IsRect, + localBoard: this.Board, isPositiveFace: true, matrix4: ocs.clone().multiply( new Matrix4().setPosition(new Vector3(0, 0, thickness))), - length: size.x, - width: size.y + length: this.Board.Width, + width: this.Board.Height })); if (opt.backDrill) { let mat = GetMirrorMat(ZAxis).setPosition(new Vector3()); - this.m_Faces.push(new Face({ + this.Faces.push(new Face({ type: BoardFaceType.NoSide, - localBoard: this.m_Board, - isRect, + localBoard: this.Board, + isRect: this.Board.IsRect, region: reg ? reg.Clone() : undefined, isPositiveFace: false, matrix4: new Matrix4().multiplyMatrices(ocs.clone(), mat), - length: size.x, - width: size.y + length: this.Board.Width, + width: this.Board.Height })); } } GetSideFaces() { - let con = this.m_Board.ContourCurve.Clone(); + let con = this.Board.ContourCurve.Clone(); let inverseZ = con.Area2 < 0; let cus = con.Explode() as Curve[]; - const highDrill = this.m_Board.BoardProcessOption.highDrill.slice(); + const highDrill = this.Board.BoardProcessOption.highDrill.slice(); //TODO: #I10I6J 矩形板起始边不是0点时,为解决当矩形板不止4边 - if (!this.m_Board.IsSpecialShape && cus.length === 4) + if (!this.Board.IsSpecialShape && cus.length === 4) { let index = Math.round(con.GetParamAtPoint(new Vector3())); highDrill.unshift(...highDrill.splice(highDrill.length - index)); @@ -89,19 +82,19 @@ export class BoardGetFace for (let i = 0; i < cus.length; i++) { let cu = cus[i]; + let length = cu.Length; if ((highDrill.length > 0 && highDrill[i] === DrillType.None) - || equaln(cu.Length, 0) + || equaln(length, 0) || cu instanceof Arc) continue; - let len = cu.Length; let mtx = GetSideFaceMtx(cu, inverseZ); - this.m_Faces.push(new Face({ + this.Faces.push(new Face({ type: BoardFaceType.Side, - localBoard: this.m_Board, + localBoard: this.Board, isPositiveFace: true, - matrix4: new Matrix4().multiplyMatrices(this.m_Board.OCS.clone(), mtx), - length: len, - width: this.m_Board.Thickness, + matrix4: new Matrix4().multiplyMatrices(this.Board.OCS.clone(), mtx), + length, + width: this.Board.Thickness, drillType: highDrill.length > 0 && highDrill[i] })); } @@ -110,13 +103,13 @@ export class BoardGetFace { let collisionFaces: Face[] = []; - for (let f1 of this.m_Faces) + for (let f1 of this.Faces) { - for (let f2 of br.m_Faces) + for (let f2 of br.Faces) { //都是正面,或者不允许侧面同侧面并且2板件类型不一样就跳过 if (f1.type === f2.type - && (f1.type === BoardFaceType.NoSide || !bInsEqual || br.m_Board.BoardType !== this.m_Board.BoardType) + && (f1.type === BoardFaceType.NoSide || !bInsEqual || br.Board.BoardType !== this.Board.BoardType) ) continue; //不共面 diff --git a/src/Geometry/DrillParse/CollisionDetection.ts b/src/Geometry/DrillParse/CollisionDetection.ts index 68209dd5b..411c84246 100644 --- a/src/Geometry/DrillParse/CollisionDetection.ts +++ b/src/Geometry/DrillParse/CollisionDetection.ts @@ -6,42 +6,40 @@ import { Box3Ext } from "../Box"; export class CollisionDetection { - private m_Boards: Board[]; - m_BoardGeList: BoardGetFace[] = []; - m_CollisonFaces: Face[] = []; - constructor(brs: Board[]) + BoardGeList: BoardGetFace[] = []; + CollisonFaces: Face[] = []; + constructor(private _Boards: Board[] = []) { - this.m_Boards = brs || []; this.Check(); } Check() { let boxCache: Map = new Map(); - let ocsInv = this.m_Boards[0].OCSInv; + let ocsInv = this._Boards[0].OCSInv; - for (let b of this.m_Boards) + for (let b of this._Boards) { if (b.BoardProcessOption.drillType !== DrillType.None) { - this.m_BoardGeList.push(new BoardGetFace(b)); + this.BoardGeList.push(new BoardGetFace(b)); boxCache.set(b, b.GetBoardBoxInMtx(ocsInv)); } } - for (let i = 0; i < this.m_BoardGeList.length; i++) + for (let i = 0; i < this.BoardGeList.length; i++) { - let f = this.m_BoardGeList[i]; - let localBox = boxCache.get(f.m_Board); + let f = this.BoardGeList[i]; + let localBox = boxCache.get(f.Board); - for (let j = i + 1; j < this.m_BoardGeList.length; j++) + for (let j = i + 1; j < this.BoardGeList.length; j++) { - let f1 = this.m_BoardGeList[j]; + let f1 = this.BoardGeList[j]; - let interBox = boxCache.get(f1.m_Board); + let interBox = boxCache.get(f1.Board); //板件包围盒相交 if (localBox.intersectsBox(interBox, 1e-2)) - this.m_CollisonFaces.push(...f.IntersectFace(f1, true)); + this.CollisonFaces.push(...f.IntersectFace(f1, true)); } } } diff --git a/src/Geometry/DrillParse/Face.ts b/src/Geometry/DrillParse/Face.ts index 6b9b5f594..bcf4016e5 100644 --- a/src/Geometry/DrillParse/Face.ts +++ b/src/Geometry/DrillParse/Face.ts @@ -1,12 +1,12 @@ import { Matrix4, Vector3 } from "three"; import { MatrixPlanarizere } from "../../Common/Matrix4Utils"; import { Board } from "../../DatabaseServices/Entity/Board"; -import { Line } from "../../DatabaseServices/Entity/Line"; import { Region } from "../../DatabaseServices/Entity/Region"; import { BoolOpeartionType } from "../../GraphicsSystem/BoolOperateUtils"; import { Box3Ext } from "../Box"; import { equaln, XAxis } from "../GeUtils"; import { BoardFaceType } from "./BoardGetFace"; +import { Polyline } from "../../DatabaseServices/Entity/Polyline"; export interface BoardFaceParams { @@ -23,68 +23,52 @@ export interface BoardFaceParams export class Face { type: BoardFaceType; - m_Length: number; - m_Width: number; - m_Region: Region; - m_LocalBoard: Board; - m_InterBoard: Board; //提供侧面的作为相交面 + Length: number; + Width: number; + private _Region: Region; + LocalBoard: Board; + InterBoard: Board; //提供侧面的作为相交面 IsPositiveFace: boolean; isEqualType: boolean = false; OCS: Matrix4 = new Matrix4(); - m_IsRect: boolean = true; - drillType: string; + IsRect: boolean = true; + DrillType: string; constructor(parameters?: BoardFaceParams) { if (parameters) { this.type = parameters.type; - this.m_Region = parameters.region; - this.m_LocalBoard = parameters.localBoard; + this._Region = parameters.region; + this.LocalBoard = parameters.localBoard; this.IsPositiveFace = parameters.isPositiveFace; - parameters.matrix4 && this.OCS.copy(parameters.matrix4); - this.m_Length = parameters.length; - this.m_Width = parameters.width; + this.OCS = parameters.matrix4; + this.Length = parameters.length; + this.Width = parameters.width; if (parameters.isRect !== undefined) - this.m_IsRect = parameters.isRect; + this.IsRect = parameters.isRect; if (parameters.drillType) - this.drillType = parameters.drillType; + this.DrillType = parameters.drillType; else - this.drillType = this.m_LocalBoard.BoardProcessOption.drillType; + this.DrillType = this.LocalBoard.BoardProcessOption.drillType; } } - get IsRect() - { - return this.m_IsRect; - } get Region() { - if (!this.m_Region) - this.m_Region = this.BuildRegion(); - return this.m_Region; + if (!this._Region) + this._Region = Region.CreateFromCurves([new Polyline().Rectangle(this.Length, this.Width)]); + return this._Region; } get OCSInv() { return new Matrix4().getInverse(this.OCS); } - private BuildRegion() - { - let p1 = new Vector3(); - let p2 = new Vector3(this.m_Length, 0); - let p3 = new Vector3(this.m_Length, this.m_Width); - let p4 = new Vector3(0, this.m_Width); - let l1 = new Line(p1, p2); - let l2 = new Line(p2, p3); - let l3 = new Line(p3, p4); - let l4 = new Line(p4, p1); - return Region.CreateFromCurves([l1, l2, l3, l4]); - } Intersect(f: Face): Face[] { //获得侧面和非侧面 let [sideFace, noSideFace] = this.type === BoardFaceType.Side ? [this, f] : [f, this]; //布尔面和被布尔面得差异矩阵 - let diffMtx = new Matrix4().getInverse(sideFace.OCS).multiply(noSideFace.OCS); + let diffMtx = sideFace.OCSInv.multiply(noSideFace.OCS); MatrixPlanarizere(diffMtx); let isSuccess = false; @@ -112,10 +96,10 @@ export class Face } else { - let retBox = new Box3Ext(new Vector3(), new Vector3(sideFace.m_Length, sideFace.m_Width)); + let retBox = new Box3Ext(new Vector3(), new Vector3(sideFace.Length, sideFace.Width)); let p1 = new Vector3().setFromMatrixPosition(diffMtx); - let p2 = new Vector3(noSideFace.m_Length, noSideFace.m_Width).applyMatrix4(diffMtx); + let p2 = new Vector3(noSideFace.Length, noSideFace.Width).applyMatrix4(diffMtx); let box3 = new Box3Ext().setFromPoints([p1, p2]); if (retBox.intersectsBox(box3)) @@ -136,11 +120,11 @@ export class Face { let newFace = new Face(); //提供侧面的板件作为相交面 - newFace.m_LocalBoard = noSideFace.m_LocalBoard; - newFace.m_InterBoard = sideFace.m_LocalBoard; + newFace.LocalBoard = noSideFace.LocalBoard; + newFace.InterBoard = sideFace.LocalBoard; - newFace.m_Length = sizes[i].x; - newFace.m_Width = sizes[i].y; + newFace.Length = sizes[i].x; + newFace.Width = sizes[i].y; let min = retBoxs[i].min; min.applyMatrix4(sideFace.OCS); @@ -149,7 +133,7 @@ export class Face newFace.OCS = sideFace.OCS.clone().setPosition(min); newFace.IsPositiveFace = sideFace.IsPositiveFace; - newFace.drillType = sideFace.drillType; + newFace.DrillType = sideFace.DrillType; //都是侧面 if (this.type === f.type) newFace.isEqualType = true; diff --git a/src/GraphicsSystem/ToolPath/FeedingToolPath.ts b/src/GraphicsSystem/ToolPath/FeedingToolPath.ts index c288e76a6..61a4b58b2 100644 --- a/src/GraphicsSystem/ToolPath/FeedingToolPath.ts +++ b/src/GraphicsSystem/ToolPath/FeedingToolPath.ts @@ -1,16 +1,21 @@ -import { Vector3 } from "three"; -import { IsRect, equalCurve } from "../../Common/CurveUtils"; +import { Matrix4, Vector3 } from "three"; +import { equalCurve, IsRect } from "../../Common/CurveUtils"; import { Singleton } from "../../Common/Singleton"; import { Contour } from "../../DatabaseServices/Contour"; import { Board, IModeling } from "../../DatabaseServices/Entity/Board"; import { Circle } from "../../DatabaseServices/Entity/Circle"; import { Curve } from "../../DatabaseServices/Entity/Curve"; +import { Line } from "../../DatabaseServices/Entity/Line"; import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { Shape } from "../../DatabaseServices/Shape"; import { ShapeManager } from "../../DatabaseServices/ShapeManager"; +import { GetSideFaceMtx } from "../../Geometry/DrillParse/BoardGetFace"; +import { isParallelTo, angleTo, XAxis, MoveMatrix } from "../../Geometry/GeUtils"; import { RegionParse, Route } from "../../Geometry/RegionParse"; +import { FaceDirection } from "../../UI/Store/BoardInterface"; import { BoolOpeartionType, isTargetCurInOrOnSourceCur } from "../BoolOperateUtils"; -import { GetCurveToInDir, OptimizeToolPath, GetOffsetCurves } from "./OptimizeToolPath"; +import { OptimizeToolPath, GetCurveToInDir, GetOffsetCurves } from "./OptimizeToolPath"; +import { ExtrudeHole } from "../../DatabaseServices/3DSolid/ExtrudeHole"; /** *计算走刀工具类 @@ -155,13 +160,38 @@ export class FeedingToolPath extends Singleton /**用于测试走刀路径 */ TestCalcPath(br: Board) { - let cus = this.CalcPath(br); + let modelings = br.BoardModeling; + let allModeling = GetModelingFromCustomDrill(br); + modelings.push(...allModeling.modeling); + let cus = this.CalcPath(modelings, br.Thickness); + + let outline = br.ContourCurve as Polyline; + let dir = Math.sign(outline.Area2); + let sideOutlines: Polyline[] = []; + //优化侧面造型模拟走刀位置 + for (let m of allModeling.sideModeling) + { + let c = outline.GetCurveAtIndex(m.dir); + let derv = c.GetFistDeriv(0); + if (dir < 0) + derv.negate(); + let mat = MoveMatrix(dir > 0 ? c.StartPoint : c.EndPoint) + .multiply(new Matrix4().makeRotationZ(angleTo(XAxis, derv))) + .multiply(MoveMatrix(new Vector3(0, -br.Thickness))); + m.shape.ApplyMatrix(mat); + let pl = new Polyline().RectangleFrom2Pt(new Vector3(), new Vector3(c.Length, br.Thickness)); + pl.ColorIndex = 6; + pl.ApplyMatrix(mat); + sideOutlines.push(pl); + } + + cus.push(...this.CalcPath(allModeling.sideModeling, br.Height)); //加入板件轮廓 cus.unshift(br.ContourCurve.Clone()); if (cus.length === 1) return cus; //加入造型外轮廓和洞 - for (let { shape, thickness } of br.BoardModeling) + for (let { shape, thickness } of modelings) { let outline = shape.Outline.Curve.Clone(); outline.Position = outline.Position.setZ(0); @@ -178,19 +208,19 @@ export class FeedingToolPath extends Singleton })); } } + cus.push(...sideOutlines); return cus; } /** * 计算走刀路径 * TODO:圆孔半径===刀半径时推送ys 显示点 */ - CalcPath(br: Board): Curve[] + CalcPath(modelings: IModeling[], thickness: number): Curve[] { let cus: Curve[] = []; - let modelings = br.BoardModeling; for (let m of modelings) { - cus.push(...this.GetModelFeedPath(br.Thickness, m)); + cus.push(...this.GetModelFeedPath(thickness, m)); } return cus; } @@ -295,3 +325,90 @@ export class FeedingToolPath extends Singleton return cons; } } +export function GetModelingFromCustomDrill(br: Board) +{ + let normal = br.Normal; + let outline = br.ContourCurve as Polyline; + let modeling: IModeling[] = []; + let sideModeling: IModeling[] = []; + + for (let [, idss] of br.DrillList) + { + for (let ids of idss) + { + for (let id of ids) + { + if (id ?.Object && !id.Object.IsErase && id.Object instanceof ExtrudeHole) + { + let en = id.Object as ExtrudeHole; + if (en.ContourCurve instanceof Circle) + continue; + let box = en.BoundingBox.applyMatrix4(br.OCSInv); + let max = box.max; + let min = box.min; + let dir: FaceDirection; + let shape = en.Shape; + shape.ApplyMatrix(en.OCS).ApplyMatrix(br.OCSInv); + let thickness: number; + if (isParallelTo(normal, en.Normal)) + { + if (min.z > br.Thickness - 1e-6) continue; + + if (max.z >= br.Thickness) + { + dir = FaceDirection.Front; + shape.Position = shape.Position.setZ(min.z); + thickness = br.Thickness - min.z; + } + else if (min.z <= 0) + { + dir = FaceDirection.Back; + thickness = max.z; + } + else continue; + if (thickness > 0) + modeling.push({ + shape, + thickness, + dir, + knifeRadius: en.KnifeRadius, + addLen: 0, + }); + } + else + { + if (min.z <= 0 || max.z >= br.Thickness) continue; + let spt = en.Position.applyMatrix4(br.OCSInv).setZ(0); + + if (outline.PtOnCurve(spt)) continue; + let line = new Line(spt, en.Position.add(en.Normal.multiplyScalar(en.Height)).applyMatrix4(br.OCSInv).setZ(0)) + let pt = outline.IntersectWith(line, 0)[0]; + if (!pt) continue; + + let index = Math.floor(outline.GetParamAtPoint(pt)); + let thickness = line.StartPoint.distanceTo(pt); + + let shape = en.Shape.ApplyMatrix(en.OCS).ApplyMatrix(br.OCSInv); + let vec = line.GetFistDeriv(0).normalize().multiplyScalar(thickness); + shape.Position = shape.Position.add(vec); + + let cu = outline.GetCurveAtIndex(index); + + shape.ApplyMatrix(new Matrix4().getInverse(GetSideFaceMtx(cu))); + + sideModeling.push({ + shape, + thickness, + dir: index, + knifeRadius: en.KnifeRadius, + addLen: 0 + }); + } + + } + else break; + } + } + } + return { modeling, sideModeling }; +} diff --git a/src/Production/Product.ts b/src/Production/Product.ts index 2b0e25afb..df74195a0 100644 --- a/src/Production/Product.ts +++ b/src/Production/Product.ts @@ -1,20 +1,21 @@ import { Matrix4, Vector2, Vector3 } from "three"; import { EBoardKeyList } from "../Common/BoardKeyList"; import { Vector2ApplyMatrix4 } from "../Common/Matrix4Utils"; -import { GangDrill, GangDrillType } from "../DatabaseServices/3DSolid/GangDrill"; +import { CylinderHole, GangDrillType } from "../DatabaseServices/3DSolid/CylinderHole"; import { Arc } from "../DatabaseServices/Entity/Arc"; -import { Board } from "../DatabaseServices/Entity/Board"; +import { Board, IModeling } from "../DatabaseServices/Entity/Board"; import { Circle } from "../DatabaseServices/Entity/Circle"; +import { Curve } from "../DatabaseServices/Entity/Curve"; +import { Line } from "../DatabaseServices/Entity/Line"; import { Polyline } from "../DatabaseServices/Entity/Polyline"; import { Vec2 } from "../Geometry/CheckIntersect"; import { AsVector2, equaln, equalv3, isParallelTo, MoveMatrix } from "../Geometry/GeUtils"; import { GetBoardHighSeal, GetBoardSealingCurves, GetSealedBoardContour as GetSealedBoardContour } from "../GraphicsSystem/CalcEdgeSealing"; -import { FeedingToolPath } from "../GraphicsSystem/ToolPath/FeedingToolPath"; +import { FeedingToolPath, GetModelingFromCustomDrill } from "../GraphicsSystem/ToolPath/FeedingToolPath"; import { FaceDirection, IHighSealedItem } from "../UI/Store/BoardInterface"; -import { Line } from "../DatabaseServices/Entity/Line"; -import { Curve } from "../DatabaseServices/Entity/Curve"; import { arrayLast } from "../Common/ArrayExt"; import { userConfig } from "../Editor/UserConfig"; +import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole"; /**板件轮廓数据 */ export interface IContourData @@ -33,7 +34,7 @@ export interface IModelingData { feeding: IContourData[]; thickness: number; - dir: FaceDirection; + dir: FaceDirection | number; knifeRadius: number; } @@ -113,14 +114,16 @@ export namespace Production originOutlinePtsBul.pts.pop(); originOutlinePtsBul.buls.pop(); + let { modeling, sideModeling } = GetBoardModelingData(br, offsetTanslation); + return { info: GetBoardInfo(br, size), originOutlin: originOutlinePtsBul, outline: outlinePtsBul, sealing: GetBoardSealingData(br), - modeling: GetBoardModelingData(br, offsetTanslation), + modeling, holes: GetBoardHolesData(br, offsetTanslation), - sideModeling: [], + sideModeling, offsetTanslation, }; } @@ -282,42 +285,52 @@ export namespace Production return sealData; } - export function GetBoardModelingData(br: Board, offsetTanslation: Vector3): IModelingData[] + export function GetBoardModelingData(br: Board, offsetTanslation: Vector3) { const tool = FeedingToolPath.GetInstance() as FeedingToolPath; const thickness = br.Thickness; - let data: IModelingData[] = []; - for (let m of br.BoardModeling) + const getModelings = (ms: IModeling[], isSide: boolean): IModelingData[] => { - let cu = m.shape.Outline.Curve; - if (cu instanceof Circle && cu.Radius < userConfig.modeling2HoleRad + 1e-6) - continue; - m.shape.ApplyMatrix(MoveMatrix(offsetTanslation.clone().negate())); - let feeding = tool.GetModelFeedPath(thickness, m).map(ConverToPolylineAndSplitArc); - if (feeding.length > 0) - data.push({ - feeding, - thickness: m.thickness, - dir: m.dir, - knifeRadius: m.knifeRadius, - }); - } - return data; + let data: IModelingData[] = []; + + for (let m of ms) + { + let cu = m.shape.Outline.Curve; + if (cu instanceof Circle && cu.Radius < userConfig.modeling2HoleRad + 1e-6) + continue; + if (!isSide) + m.shape.ApplyMatrix(MoveMatrix(offsetTanslation.clone().negate())); + let feeding = tool.GetModelFeedPath(thickness, m).map(ConverToPolylineAndSplitArc); + if (feeding.length > 0) + data.push({ + feeding, + thickness: m.thickness, + dir: m.dir, + knifeRadius: m.knifeRadius, + }); + } + return data; + }; + + let allModeling = GetModelingFromCustomDrill(br); + + let modeling = getModelings([...br.BoardModeling, ...allModeling.modeling], false).filter(f => f.feeding.length > 0); + + let sideModeling = getModelings(allModeling.sideModeling, true).filter(f => f.feeding.length > 0); + + return { modeling, sideModeling }; } export function GetBoardHolesData(br: Board, offsetTanslation: Vector3): IBoardHoleInfo { let drillList = br.DrillList; - let processData = br.BoardProcessOption; let data: IBoardHoleInfo = { frontBackHoles: [], sideHoles: [] }; let brNormal = br.Normal; - let outline = br.ContourCurve; - let roMat = new Matrix4().extractRotation(br.OCSInv); for (let [, driss] of drillList) { for (let dris of driss) @@ -326,101 +339,11 @@ export namespace Production { if (!dId || dId.IsErase) continue; - let d = dId.Object as GangDrill; - let position = d.Position.applyMatrix4(br.OCSInv); - let holes = data.frontBackHoles; - let face: number; - let isPush = false; - let endPt: Vector3; - let depth = d.Height; - if (d.Type === GangDrillType.Pxl || d.Type === GangDrillType.WoodPXL) - { - if (isParallelTo(d.Normal, brNormal)) - { - if (position.x <= 0 || position.x >= br.Width || position.y <= 0 || position.y >= br.Height) continue; - - position.sub(offsetTanslation); - face = processData[EBoardKeyList.BigHole]; - isPush = true; - } - } - else if (d.Type === GangDrillType.Ljg || d.Type === GangDrillType.Wood) - { - if (!isParallelTo(d.Normal, brNormal)) - { - let z = position.z; - if (z <= 0 || z >= br.Thickness) continue; - - let line = new Line(position.clone().setZ(0), position.clone().setZ(0).add(d.Normal.multiplyScalar(d.Height).applyMatrix4(roMat))); - let pt = outline.IntersectWith(line, 0)[0]; - if (!pt) - { - console.warn("可能有排钻超出板件外"); - continue; - } - position = pt.clone().setZ(z); - for (let p of [line.StartPoint, line.EndPoint]) - { - if (outline.PtInCurve(p)) - { - endPt = p.setZ(z); - break; - } - } - if (!endPt) - { - console.warn("排钻位置有问题"); - continue; - } - holes = data.sideHoles; - face = Math.floor(outline.GetParamAtPoint(pt)); - isPush = true; - depth = position.distanceTo(endPt); - } - else if (d.Type === GangDrillType.Wood) - { - face = position.z > 0 ? FaceDirection.Front : FaceDirection.Back; - holes = data.frontBackHoles; - if (position.z > 0) - { - let z1 = position.z - d.Height; - if (z1 > 0 && z1 < br.Thickness) - { - depth = br.Thickness - z1; - isPush = true; - } - } - else - { - let z1 = position.z + d.Height; - if (z1 > 0 && z1 < br.Thickness) - { - depth = z1; - isPush = true; - } - } - position.sub(offsetTanslation); - } - } + let d = dId.Object as CylinderHole; + if (d instanceof ExtrudeHole) + ParseExtrudeHoles(d, br, offsetTanslation, data); else - { - if (isParallelTo(d.Normal, br.Normal)) - { - if (position.x <= 0 || position.x >= br.Width || position.y <= 0 || position.y >= br.Height) continue; - position.sub(offsetTanslation); - holes = data.frontBackHoles; - face = !equalv3(d.Normal, brNormal) ? 0 : 1; - isPush = true; - } - } - isPush && holes.push({ - type: d.Type, - position, - radius: d.Radius, - depth, - face, - endPt, - }); + ParseCylHoles(d, br, offsetTanslation, data); } } } @@ -429,7 +352,7 @@ export namespace Production { if (!nid || !nid.Object || nid.IsErase) continue; - let nail = nid.Object as GangDrill; + let nail = nid.Object as CylinderHole; if (isParallelTo(nail.Normal, brNormal)) { let nailPosition = nail.Position.applyMatrix4(br.OCSInv); @@ -466,5 +389,182 @@ export namespace Production return data; } + /**分析常规排钻 */ + function ParseCylHoles(d: CylinderHole, br: Board, offsetTanslation: Vector3, data: IBoardHoleInfo) + { + let processData = br.BoardProcessOption; + let brNormal = br.Normal; + let roMat = new Matrix4().extractRotation(br.OCSInv); + let outline = br.ContourCurve; + let position = d.Position.applyMatrix4(br.OCSInv); + let holes = data.frontBackHoles; + let face: number; + let isPush = false; + let endPt: Vector3; + let depth = d.Height; + if (d.Type === GangDrillType.Pxl || d.Type === GangDrillType.WoodPXL) + { + if (isParallelTo(d.Normal, brNormal)) + { + if (position.x <= 0 || position.x >= br.Width || position.y <= 0 || position.y >= br.Height) return; + position.sub(offsetTanslation); + face = processData[EBoardKeyList.BigHole]; + isPush = true; + } + } + else if (d.Type === GangDrillType.Ljg || d.Type === GangDrillType.Wood) + { + if (!isParallelTo(d.Normal, brNormal)) + { + let z = position.z; + let line = new Line(position.clone().setZ(0), position.clone().setZ(0).add(d.Normal.multiplyScalar(d.Height).applyMatrix4(roMat))); + let pt = outline.IntersectWith(line, 0)[0]; + if (!pt) + { + console.warn("可能有排钻超出板件外"); + return; + } + position = pt.clone().setZ(z); + for (let p of [line.StartPoint, line.EndPoint]) + { + if (outline.PtInCurve(p)) + { + endPt = p.setZ(z); + break; + } + } + if (!endPt) + { + console.warn("排钻位置有问题"); + return; + } + holes = data.sideHoles; + face = Math.floor(outline.GetParamAtPoint(pt)); + isPush = true; + depth = position.distanceTo(endPt); + } + else if (d.Type === GangDrillType.Wood) + { + face = position.z > 0 ? FaceDirection.Front : FaceDirection.Back; + holes = data.frontBackHoles; + if (position.z > 0) + { + let z1 = position.z - d.Height; + if (z1 > 0 && z1 < br.Thickness) + { + depth = br.Thickness - z1; + isPush = true; + } + } + else + { + let z1 = position.z + d.Height; + if (z1 > 0 && z1 < br.Thickness) + { + depth = z1; + isPush = true; + } + } + position.sub(offsetTanslation); + } + } + else + { + if (isParallelTo(d.Normal, br.Normal)) + { + if (position.x <= 0 || position.x >= br.Width || position.y <= 0 || position.y >= br.Height) return; + position.sub(offsetTanslation); + holes = data.frontBackHoles; + face = !equalv3(d.Normal, brNormal) ? 0 : 1; + isPush = true; + } + } + isPush && holes.push({ + type: d.Type, + position, + radius: d.Radius, + depth, + face, + endPt, + }); + } + /**分析自定义圆柱排钻 */ + function ParseExtrudeHoles(d: ExtrudeHole, br: Board, offsetTanslation: Vector3, data: IBoardHoleInfo) + { + let brNormal = br.Normal; + let outline = br.ContourCurve; + let cir = d.ContourCurve; + if (cir instanceof Circle) + { + let diffMtx = br.OCSInv.multiply(d.OCS); + let nor = d.Normal; + let sp = cir.Center.applyMatrix4(diffMtx); + let ep = cir.Center.add(new Vector3(0, 0, d.Height)).applyMatrix4(diffMtx); + + if (isParallelTo(nor, brNormal)) + { + let z0 = Math.min(sp.z, ep.z); + let z1 = Math.max(sp.z, ep.z); + let p = sp.clone().setZ(0).sub(offsetTanslation); + + if (Math.max(z0, 0) < Math.min(z1, br.Thickness) - 1e-6) + { + data.frontBackHoles.push({ + type: GangDrillType.Pxl, + position: z0 < 1e-6 ? p : p.setZ(br.Thickness), + radius: cir.Radius, + depth: z0 < 1e-6 ? z1 : br.Thickness - z0, + face: z0 < 1e-6 ? DrillingFace.Back : DrillingFace.Front, + }); + } + } + else + { + let oldZ = sp.z; + let [minX, maxX] = sp.x < ep.x ? [sp.x, ep.x] : [ep.x, sp.x]; + let [minY, maxY] = sp.y < ep.y ? [sp.y, ep.y] : [ep.y, sp.y]; + + + if (sp.z > cir.Radius + && sp.z < br.Thickness - cir.Radius + && Math.max(minX, 0) < Math.min(br.Width, maxX) + 1e-6 + && Math.max(minY, 0) < Math.min(br.Height, maxY) + 1e-6 + ) + { + sp.setZ(0); + ep.setZ(0); + let line = new Line(sp, ep); + let pt = outline.IntersectWith(line, 0)[0]; + if (!pt) + { + console.error("排钻嵌在板件内部"); + return; + } + let position = pt.clone().setZ(oldZ); + let endPt: Vector3; + let face = Math.floor(outline.GetParamAtPoint(pt)); + for (let p of [line.StartPoint, line.EndPoint]) + { + if (outline.PtInCurve(p)) + { + endPt = p.setZ(oldZ); + break; + } + } + if (!endPt) + return; + let depth = position.distanceTo(endPt); + data.sideHoles.push({ + type: GangDrillType.Ljg, + endPt, + position, + radius: cir.Radius, + depth, + face, + }); + } + } + } + } } diff --git a/src/UI/Components/Board/DrillCommon.tsx b/src/UI/Components/Board/DrillCommon.tsx index e4c55d567..ea23638cc 100644 --- a/src/UI/Components/Board/DrillCommon.tsx +++ b/src/UI/Components/Board/DrillCommon.tsx @@ -1,8 +1,11 @@ -import { Button, Card, Classes, Popover, Position, Radio, RadioGroup, Intent, HTMLSelect } from '@blueprintjs/core'; -import { observable } from 'mobx'; +import { Button, Card, Checkbox, Classes, Intent, IOptionProps, Popover, Position, Radio, RadioGroup, HTMLSelect } from '@blueprintjs/core'; +import { observable, toJS } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { DirUrl, TemplateUrls } from '../../../Common/HostUrl'; +import { DirectoryId, PostJson, RequestStatus } from '../../../Common/Request'; import { DrillStore } from '../../Store/DrillStore'; +import { end } from 'xaop'; @observer export class DrillTypeCom extends React.Component<{ store: DrillStore; }, { typeName: string; }> @@ -114,3 +117,138 @@ export class DrillTypeCom extends React.Component<{ store: DrillStore; }, { type ); } } + +@observer +export class SelectDrillTemp extends React.Component<{ store: DrillStore; }, {}> +{ + @observable drillingTempList: IOptionProps[] = []; + @observable drillingDirList: IOptionProps[] = []; + private _dirCache: Map = new Map(); + private _fun: Function; + async UNSAFE_componentWillMount() + { + await this.getDirList(); + this._fun = end(this.props.store, this.props.store.ChangeRules, async () => + { + if (this.props.store.m_Option.tempDirId) + await this.getTempList(this.props.store.m_Option.tempDirId); + else + this.drillingTempList.length = 0; + }); + } + + componentWillUnmount() + { + if (this._fun) + { + this._fun(); + this._fun = null; + } + } + render() + { + let option = this.props.store.m_Option; + return ( +
+ + { + option.useTemp = !option.useTemp; + if (option.useTemp) + await this.getDirList(); + }} + /> + { + this.drillingDirList.length > 0 && + } + +
+ ); + } + private getTempList = async (dir_id: string) => + { + this.props.store.m_Option.tempDirId = dir_id; + if (this._dirCache.has(dir_id)) + { + observable(this.drillingTempList).replace(this._dirCache.get(dir_id)); + } + else + { + let data = await PostJson(TemplateUrls.list, { dir_id }); + + if (data.err_code === RequestStatus.Ok && data.modules) + { + observable(this.drillingTempList).replace(data.modules.map(file => + { + return { + label: file.name, + value: file.module_id + }; + })); + this._dirCache.set(dir_id, toJS(this.drillingTempList)); + } + } + }; + private getDirList = async () => + { + let data = await PostJson(DirUrl.query, { dir_type: DirectoryId.DrillingDir }); + if (data.err_code === RequestStatus.Ok) + { + if (data.dirs.length === 0) + { + this.drillingDirList.length = 0; + await this.getTempList(DirectoryId.DrillingDir); + } + else + { + observable(this.drillingDirList).replace(data.dirs.map(dir => + { + return { + label: dir.dir_name, + value: dir.dir_id + }; + })); + this.drillingDirList.unshift({ + label: "/", + value: DirectoryId.DrillingDir + }); + if (this.props.store.m_Option.tempDirId) + { + await this.getTempList(this.props.store.m_Option.tempDirId); + } + } + } + }; + private handleChangeDirs = async (e: React.FormEvent) => + { + let selectEl = e.target as HTMLSelectElement; + selectEl.options[0].disabled = true; + if (selectEl.value) + await this.getTempList(selectEl.value); + }; + private handleChangeTemp = (e: React.FormEvent) => + { + let selectEl = e.target as HTMLSelectElement; + selectEl.options[0].disabled = true; + if (selectEl.value) + this.props.store.m_Option.tempId = selectEl.value; + }; +} diff --git a/src/UI/Components/Board/GangDrillModal.tsx b/src/UI/Components/Board/GangDrillModal.tsx index 1da5c8937..cb775904a 100644 --- a/src/UI/Components/Board/GangDrillModal.tsx +++ b/src/UI/Components/Board/GangDrillModal.tsx @@ -1,22 +1,22 @@ -import { Button, Checkbox, Classes, HTMLSelect, Icon, Radio, RadioGroup } from '@blueprintjs/core'; +import { Button, Checkbox, Classes, Icon, Radio, RadioGroup } from '@blueprintjs/core'; import { inject, observer } from 'mobx-react'; import * as React from 'react'; import * as xaop from 'xaop'; import { app } from '../../../ApplicationServices/Application'; import { CheckObjectType } from '../../../Common/CheckoutVaildValue'; +import { safeEval } from '../../../Common/eval'; import { KeyBoard } from '../../../Common/KeyEnum'; import { commandMachine } from '../../../Editor/CommandMachine'; import { SpacingType } from '../../Store/drillInterface'; import { DrillStore } from '../../Store/DrillStore'; +import { userConfigStore } from '../../Store/UserConfigStore'; import { ModalState } from '../Modal/ModalsManage'; import { ToasterInput } from '../Toaster'; import { ItemName, SetBoardDataItem } from './BoardCommon'; import { BoardModalType } from './BoardModal'; +import { DrillTypeCom, SelectDrillTemp } from './DrillCommon'; import { DrillRulesComponent } from './DrillRules'; import { UserConfig } from './UserConfig'; -import { userConfigStore } from '../../Store/UserConfigStore'; -import { DrillTypeCom } from './DrillCommon'; -import { safeEval } from '../../../Common/eval'; @inject('store') @observer @@ -52,7 +52,8 @@ export class DrillModal extends React.Component<{ store?: DrillStore; }, {}> { userConfigStore.SaveConfig(BoardModalType.Dr, this.props.store, false); app.Editor.ModalManage.Clear(); commandMachine.ExecCommand('PZ'); - }; + } + UNSAFE_componentWillMount() { //注册事件 @@ -253,20 +254,9 @@ export class DrillModal extends React.Component<{ store?: DrillStore; }, {}> { ) } - -
- - -
+
木销参数
void; + dataList?: any[]; + select?: (e: React.FormEvent, data: any) => void; + isRename: IObservableValue; + updata: (name: string, dir: IDirectoryProps, call: Function) => void; + getData?: () => void; + info: { id: string; name: string; }; +} + +@observer +export class DrillingTemplateList extends React.Component { + private _cameraFiler: CADFiler; + constructor(props) + { + super(props); + this.state = { + isContextMenuOpen: false + }; + } + private renderToasterMessage = () => + { + return ( +
+ 正在编辑排钻模板 +
+
+
+ ); + }; + public render() + { + return ( +
    + { + this.props.dataList.map(temp => + { + return ( +
  • this.handleMounseDown(e, temp)} + style={{ + background: this.props.info.id === temp.module_id && "rgba(162, 186, 197, 0.34)", + }} + > +
    + +
    +

    {temp.name}

    + node.parentElement.parentElement.style.zIndex = "33"} + content={ + +

    确认删除文件

    +
    +
    +
    + } + target={
  • + ); + }) + } +
+ ); + } + private handleMounseDown = (e: React.MouseEvent, temp: any) => + { + this.props.info.id = temp.module_id; + this.props.info.name = temp.name; + if (e.button === MouseKey.Right) + { + this.showContextMenu(e, temp); + } + }; + + //展示右键菜单 + private showContextMenu = (e: React.MouseEvent, temp: { module_id: string; }) => + { + ContextMenu.show( + + this.props.isRename.set(true)} + /> + this.startEditorTopline(temp)} + /> + , + { left: e.clientX, top: e.clientY }, + () => this.setState({ isContextMenuOpen: false }), + ); + this.setState({ isContextMenuOpen: true }); + + e.stopPropagation(); + e.preventDefault(); + }; + private startEditorTopline = async (temp: { module_id: string; }) => + { + TempEditor.Start(); + app.Editor.ModalManage.Clear(); + + let data = await PostJson(TemplateUrls.detail, { module_id: temp.module_id }); + + if (data.err_code === RequestStatus.Ok) + { + let files = JSON.parse(inflate(data.modules.file)); + let ens = files.map(ExtrudeDrillFileIn) as ExtrudeSolid[]; + ens.forEach(e => app.Database.ModelSpace.Append(e)); + + this._cameraFiler = new CADFiler; + app.Viewer.CameraCtrl.WriteFile(this._cameraFiler); + app.Viewer.ZoomAll(); + AppToaster.show({ + message: this.renderToasterMessage(), + intent: Intent.PRIMARY, + timeout: 0, + onDismiss: this.exitEditor + }); + } + }; + private exitEditor = () => + { + if (!this._cameraFiler) return; + app.Viewer.CameraCtrl.ReadFile(this._cameraFiler); + TempEditor.End(); + this._cameraFiler = undefined; + app.Editor.SelectCtrl.Cancel(); + app.Editor.ModalManage.RenderModal(DrillingTemplateManage, ModalPosition.Old, {}); + }; + handleUpdateTemp = async () => + { + await app.Editor.ModalManage.EndExecingCmd(); + let ens = app.Viewer.VisibleEntitys.filter(en => en instanceof ExtrudeHole) as ExtrudeHole[]; + if (ens.length > 0) + { + let module_id = this.props.info.id; + let logo = await GetEntitysLogo(ens); + + let dataList = []; + //基点移动到基点 + for (let en of ens) + { + let vf = new CADFiler(); + en.WriteFile(vf); + dataList.push(vf.Data); + } + let filesJson = JSON.stringify(dataList); + let data = await PostJson(TemplateUrls.update, { + module_id, + logo, + file: deflate(filesJson), + zip_type: "gzip", + }); + + AppToaster.clear(); + if (data.err_code === RequestStatus.Ok) + { + //更新缓存的自定义排钻实体 + ens = []; + for (let file of dataList) + ens.push(ExtrudeDrillFileIn(file)); + appCache.set(StoreageKeys.DrillTemp + module_id, ens); + await this.props.getData(); + AppToaster.show({ + message: "排钻模板修改成功", + timeout: 1500, + intent: Intent.SUCCESS, + }); + } + + } + else + { + AppToaster.show({ + message: "修改失败,可能当前图上不存在排钻实体,请重试或者取消", + timeout: 1200, + intent: Intent.DANGER, + }); + } + }; +} diff --git a/src/UI/Components/Modal/DrillingTemplateManage.tsx b/src/UI/Components/Modal/DrillingTemplateManage.tsx new file mode 100644 index 000000000..823be14f3 --- /dev/null +++ b/src/UI/Components/Modal/DrillingTemplateManage.tsx @@ -0,0 +1,252 @@ +import { Button, Classes, Icon, Intent, MenuItem } from '@blueprintjs/core'; +import { observable } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { app } from '../../../ApplicationServices/Application'; +import { TemplateUrls } from '../../../Common/HostUrl'; +import { DirectoryId, PostJson, RequestStatus, IResponseData } from '../../../Common/Request'; +import { deflate, ExtrudeDrillFileIn, GetEntitysLogo, inflate } from '../../../Common/SerializeMaterial'; +import { CADFiler } from '../../../DatabaseServices/CADFiler'; +import { CommandWrap } from '../../../Editor/CommandMachine'; +import { PromptStatus } from '../../../Editor/PromptResult'; +import { MoveMatrix } from '../../../Geometry/GeUtils'; +import { CommonPanel, IDirectoryProps } from '../SourceManage/CommonPanel'; +import { HandleDirComponent } from '../SourceManage/HandleDirComponent'; +import { AppToaster } from '../Toaster'; +import { DrillingTemplateList } from './DrillingTemplateList'; +import { ExtrudeHole } from '../../../DatabaseServices/3DSolid/ExtrudeHole'; + +@observer +export class DrillingTemplateManage extends React.Component<{}> { + private canCreateTemplate = observable.box(false); + @observable private currentInfo = { id: "", name: "" }; + renderNav = () => + { + return ( +