!1938 重构:标注样式 标注板件(AutoDimBrs,FastDim)

pull/2025/MERGE
林三 2 years ago committed by ChenX
parent 5ad2c7251f
commit 808351edd5

@ -1,4 +1,4 @@
import { Line } from "../../src/api";
import { Line } from "../../src/DatabaseServices/Entity/Line";
import { RegionParse } from "../../src/Geometry/RegionParse";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";

@ -1,6 +1,6 @@
import { Vector3 } from "three";
import { CADFiler } from "../../src/api";
import { MakeMirrorMtx } from "../../src/Common/Matrix4Utils";
import { CADFiler } from "../../src/DatabaseServices/CADFiler";
import { XAxis } from "../../src/Geometry/GeUtils";
import { LoadBoardsFromFileData } from "../Utils/LoadEntity.util";

@ -1,6 +1,6 @@
import { BoolOpeartionType } from "../../src/api";
import { Board } from "../../src/DatabaseServices/Entity/Board";
import { Region } from "../../src/DatabaseServices/Entity/Region";
import { BoolOpeartionType } from "../../src/GraphicsSystem/BoolOperateUtils";
import "../Utils/jest.util";
import { LoadEntityFromFileData, LoadRegionsFromFileData } from "../Utils/LoadEntity.util";

@ -1,4 +1,4 @@
import { Circle } from "../../src/api";
import { Circle } from "../../src/DatabaseServices/Entity/Circle";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
test('圆的包围盒', () =>

@ -1,5 +1,5 @@
import { Polyline } from "../../src/api";
import { Contour } from "../../src/DatabaseServices/Contour";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
test('多个布尔错误', () =>

@ -1,5 +1,5 @@
import { Board } from "../../src/DatabaseServices/Entity/Board";
import { GetSealedBoardContour } from "../../src/GraphicsSystem/CalcEdgeSealing";
import { Board } from "../../src/ueapi";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
test('无法计算封边', () =>

@ -1,8 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`changev 1`] = `"[8,101,1,2,1,false,0,1,\\"\\",2,2,false,0,1,\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[2,3,4],[0,0,0],2,4,false,0,2,0,2,3,false,0,2,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",2,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[0,0,0],[0,0,0]],\\"\\",100,1,\\"ObjectAllDataHistoryRecord\\",1,1,\\"AllObjectData\\",1,[8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[0,0,0],[0,0,0]],\\"\\",\\"\\",100,2,5,false,0,0,1,2,6,false,0,0,1,2,7,false,0,1,\\"\\",2,8,false,0,0,2,9,false,0,0,1,2,10,false,0,1,\\"\\",2,11,false,0,0,0]"`;
exports[`changev 1`] = `"[9,101,1,2,1,false,0,1,\\"\\",2,2,false,0,1,\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[2,3,4],[0,0,0],2,4,false,0,2,0,2,3,false,0,2,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",2,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[0,0,0],[0,0,0]],\\"\\",100,1,\\"ObjectAllDataHistoryRecord\\",1,1,\\"AllObjectData\\",1,[8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[0,0,0],[0,0,0]],\\"\\",\\"\\",100,2,5,false,0,0,1,2,6,false,0,0,1,2,7,false,0,1,\\"\\",2,8,false,0,0,2,9,false,0,0,1,2,10,false,0,1,\\"\\",2,11,false,0,0,0,1,2,12,false,0,2,0,0]"`;
exports[`创建 修改 撤销撤销 重做重做 撤销 重做 1`] = `"[8,101,1,2,1,false,0,1,\\"\\",2,2,false,0,1,\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0],2,4,false,0,2,0,2,3,false,0,2,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0]],\\"\\",2,5,false,0,0,1,2,6,false,0,0,1,2,7,false,0,1,\\"\\",2,8,false,0,0,2,9,false,0,0,1,2,10,false,0,1,\\"\\",2,11,false,0,0,0]"`;
exports[`创建 修改 撤销撤销 重做重做 撤销 重做 1`] = `"[9,101,1,2,1,false,0,1,\\"\\",2,2,false,0,1,\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0],2,4,false,0,2,0,2,3,false,0,2,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0]],\\"\\",2,5,false,0,0,1,2,6,false,0,0,1,2,7,false,0,1,\\"\\",2,8,false,0,0,2,9,false,0,0,1,2,10,false,0,1,\\"\\",2,11,false,0,0,0,1,2,12,false,0,2,0,0]"`;
exports[`创建 修改 撤销撤销 重做重做 撤销 重做 2`] = `"[\\"HistoricManage\\",1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,1,\\"HistorycRecord\\",1,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[\\"Line\\",8,2,100,false,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,true,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,1,[1,2,3],[0,0,0]],\\"\\"]"`;

@ -2,7 +2,7 @@
exports[`wblockClone 1`] = `
Array [
8,
9,
102,
1,
2,
@ -147,12 +147,20 @@ Array [
0,
0,
0,
1,
2,
12,
false,
0,
2,
0,
0,
]
`;
exports[`wblockClone 2`] = `
Array [
8,
9,
104,
1,
2,
@ -372,12 +380,20 @@ Array [
0,
0,
0,
1,
2,
12,
false,
0,
2,
0,
0,
]
`;
exports[`wblockClone 3`] = `
Array [
8,
9,
102,
1,
2,
@ -522,5 +538,13 @@ Array [
0,
0,
0,
1,
2,
12,
false,
0,
2,
0,
0,
]
`;

@ -0,0 +1,59 @@
import { Euler, Matrix4, Vector3 } from "three";
import { equaln } from "../../src/Geometry/GeUtils";
// file.only
//证明 EU和旋转矩阵复合的转换
test('Euler', () =>
{
let x = 0.5,
y = 2,
z = 1;
let eu = new Euler(x, y, z, "ZYX");
let mtxEu = new Matrix4().makeRotationFromEuler(eu);//Eu旋转矩阵
let mtxx = new Matrix4().makeRotationX(x);
let mtxy = new Matrix4().makeRotationY(y);
let mtxz = new Matrix4().makeRotationZ(z);
let mtxCom = mtxx.clone().premultiply(mtxy).premultiply(mtxz);//复合矩阵 z * y * x
for (let i = 0; i < mtxEu.elements.length; i++)
expect(equaln(mtxEu.elements[i], mtxCom.elements[i])).toBeTruthy();//证明 z*y*x =Euler("ZYX")
let p = new Vector3(1, 2, 3);
p.clone().applyMatrix4(mtxCom);//?
p.clone().applyMatrix4(mtxx).applyMatrix4(mtxy).applyMatrix4(mtxz);//?
//证明了EU角度不可逆转
new Euler(0, 0, 0, "ZYX").setFromRotationMatrix(mtxCom);//?
//证明了这个不能逆转..
let euT = new Euler(Math.PI / 2, Math.PI / 2, 0, "ZYX");
euT.setFromRotationMatrix(new Matrix4().makeRotationFromEuler(euT));//?
});
//证明 mtxa * mtxb = p.apply(mtxb).apply(mtxa)
test('mtx a*b', () =>
{
let mtx1 = new Matrix4().setPosition(100, 0, 0);
let mtx2 = new Matrix4().makeRotationZ(Math.PI / 2);//旋转90度
let p = new Vector3(100, 0, 0);
mtx1.multiply(mtx2);
p.applyMatrix4(mtx1);
p; //?
});
test('mtx a*b2', () =>
{
let mtx1 = new Matrix4().setPosition(100, 0, 0);
let mtx2 = new Matrix4().makeRotationZ(Math.PI / 2);
mtx1.premultiply(mtx2);
let p = new Vector3(100, 0, 0);
p.applyMatrix4(mtx1);
p; //?
});

@ -1,5 +1,5 @@
import { Polyline } from "../../src/api";
import { Contour } from "../../src/DatabaseServices/Contour";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import "../Utils/jest.util";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";

@ -1,4 +1,4 @@
import { Polyline } from "../../src/api";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import { LoadCurvesFromFileData } from "../Utils/LoadEntity.util";
describe("多段线自交测试", () =>

@ -1,4 +1,4 @@
import { Polyline } from "../../src/api";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import "../Utils/jest.util";
import { LoadCurvesFromFileData } from "../Utils/LoadEntity.util";

@ -1,4 +1,5 @@
import { IsRect, Polyline } from "../../src/api";
import { IsRect } from "../../src/Common/CurveUtils";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import { RectOffset } from "../../src/GraphicsSystem/ToolPath/OptimizeToolPath";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";

@ -1,13 +1,13 @@
import { CADFiler } from "../../src/api";
import "../Utils/jest.util";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
LoadEntityFromFileData;
//如果不延迟导入,则导致循环依赖错误
import { inflateBase64 } from "../../src/Common/inflate";
import { CADFiler } from "../../src/DatabaseServices/CADFiler";
import { Database } from "../../src/DatabaseServices/Database";
import { RoomWallBase } from "../../src/DatabaseServices/Room/Entity/Wall/RoomWallBase";
import { RoomWallLine } from "../../src/DatabaseServices/Room/Entity/Wall/RoomWallLine";
import { RoomWallParse } from "../../src/ueapi";
import { RoomWallParse } from "../../src/DatabaseServices/Room/ParseService/RoomWallParse";
test('网洞绘制错误', () =>
{

@ -2,7 +2,6 @@ import { Vector3 } from "three";
import { RoomHolePolyline } from "../../src/DatabaseServices/Room/Entity/Wall/Hole/RoomHolePolyline";
import { RoomWallLine } from "../../src/DatabaseServices/Room/Entity/Wall/RoomWallLine";
import { RoomIHoleParseAndModify, RoomLHoleParseAndModify } from "../../src/DatabaseServices/Room/ParseService/Hole/RoomIHoleParseAndModify";
import { RoomWallParse, UpdateRelevanceWallHole } from "../../src/ueapi";
import "../Utils/jest.util";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
LoadEntityFromFileData;
@ -11,6 +10,8 @@ import { CADFiler } from "../../src/DatabaseServices/CADFiler";
import { Database } from "../../src/DatabaseServices/Database";
import { RoomWallArc } from "../../src/DatabaseServices/Room/Entity/Wall/RoomWallArc";
import { RoomWallBase } from "../../src/DatabaseServices/Room/Entity/Wall/RoomWallBase";
import { RoomWallParse } from "../../src/DatabaseServices/Room/ParseService/RoomWallParse";
import { UpdateRelevanceWallHole } from "../../src/Reactor/RoomHoleReactor";
test('墙洞1', () =>

@ -6,6 +6,7 @@ import { Entity } from "../../src/DatabaseServices/Entity/Entity";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import { Region } from "../../src/DatabaseServices/Entity/Region";
import { HardwareTopline } from "../../src/DatabaseServices/Hardware/HardwareTopline";
import { RoomHolePolyline } from "../../src/DatabaseServices/Room/Entity/Wall/Hole/RoomHolePolyline";
import { RoomWallArc } from "../../src/DatabaseServices/Room/Entity/Wall/RoomWallArc";
import { RoomWallLine } from "../../src/DatabaseServices/Room/Entity/Wall/RoomWallLine";
import { TemplateStretchGripAction } from "../../src/DatabaseServices/Template/Action/TemplateStretchGripAction";
@ -21,6 +22,7 @@ Factory(TemplateLeftRightBoardRecord);
TemplateSizeBoard;
TemplateStretchGripAction;
RoomWallLine;
RoomHolePolyline;
RoomWallArc;
Text;

@ -1,5 +1,6 @@
import { MathUtils } from "three";
import { Polyline, VKnifToolPath } from "../../src/api";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import { VKnifToolPath } from "../../src/GraphicsSystem/ToolPath/VKnifToolPath";
import { LoadEntityFromFileData } from "../Utils/LoadEntity.util";
test('V型刀测试', () =>

@ -83,7 +83,7 @@
"ts-node": "^10.8.1",
"tsconfig-paths": "^3.14.1",
"tslib": "^2.4.0",
"typescript": "^4.8.2",
"typescript": "^4.8.3",
"url-loader": "^4.1.1",
"wallaby-webpack": "^3.9.16",
"webpack": "^5.74.0",

@ -1,35 +1,23 @@
import { Matrix4, Vector2, Vector3 } from "three";
import { Matrix4, Vector3 } from "three";
import { app } from "../../ApplicationServices/Application";
import { arrayRemoveDuplicateBySort, arraySortByNumber } from "../../Common/ArrayExt";
import { AlignedDimension } from "../../DatabaseServices/Dimension/AlignedDimension";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Entity } from "../../DatabaseServices/Entity/Entity";
import { HardwareCompositeEntity } from "../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { TemplateRecord } from "../../DatabaseServices/Template/TemplateRecord";
import { Command } from "../../Editor/CommandMachine";
import { JigUtils } from "../../Editor/JigUtils";
import { PromptStatus } from "../../Editor/PromptResult";
import { equaln, equalnn } from "../../Geometry/GeUtils";
import AutoDimBoardPanel from "../../UI/Components/AutoDimBoard";
import { BoardModalType } from "../../UI/Components/Board/BoardModalType";
import { IConfigOption } from "../../UI/Components/Board/UserConfig";
import { equalv3, MoveMatrix, ZeroVec } from "../../Geometry/GeUtils";
import { AutoDimBoardPanel } from "../../UI/Components/AutoDimBoard";
import { ModalState } from "../../UI/Components/Modal/ModalInterface";
import { IConfigStore } from "../../UI/Store/BoardStore";
import { userConfigStore } from "../../UI/Store/UserConfigStore";
import { IsHandle } from "../HideSelect/HideSelectUtils";
import { autoDimBoardTool } from "./AutoDimBrsTool";
import { BoardType } from "../../UI/Store/BoardInterface";
import { IsDoor, IsHandle, IsHinge } from "../HideSelect/HideSelectUtils";
import { autoDimBrsStore } from "./AutoDimBrsStore";
import { DimBoards } from "./DimBoards";
export class Command_AutoDimBrs implements Command
{
maxThickness: number = 0;
store: AutoDimBrsStore;
async exec()
{
//加入配置
if (!this.store) this.store = new AutoDimBrsStore;
let promiseLoadConfig = userConfigStore.UpdateBoardOption(this.store.configName, BoardModalType.AutoDimBrs, this.store);
//选择板件
let enRes = await app.Editor.GetSelection({
Msg: `选择需要标注的柜体`,
@ -53,178 +41,92 @@ export class Command_AutoDimBrs implements Command
if (enRes.Status === PromptStatus.Cancel)
return;
await promiseLoadConfig;//等待载入配置
let brs = enRes.SelectSet.SelectEntityList as Board[];
brs = this.backBoards(brs);//获取所有板件包括复合实体内的板件
app.Editor.ModalManage.RenderModal(AutoDimBoardPanel, { dimType: this.store.config.option.dimType });
let brs = this.GetAllBoards(enRes.SelectSet.SelectEntityList);//获取所有板件包括复合实体内的板件
let store = autoDimBrsStore;
app.Editor.ModalManage.RenderModeless(AutoDimBoardPanel, { store: store }, { canMinimize: false });
let res = await app.Editor.ModalManage.Wait();
if (res.Status === ModalState.Ok)
{
if (res.Data.type !== this.store.config.option.dimType)
{
//上传配置
this.store.config.option.dimType = res.Data.type;
let tool = new DimBoards;
tool.EanbleParseGroups = store.m_Option.useParseGroups === "0" ? true : false;
userConfigStore.SaveConfig(BoardModalType.AutoDimBrs, this.store, { toaster: false });
}
autoDimBoardTool.Do(brs, res.Data.type);
}
}
/**
*
* @param brs
* @param drawCS
*/
DrawDim(brs: Board[], drawCS: Matrix4, textRotation?: number, needJig: boolean = false, useMaxZ: boolean = false, isLeadOutFlipped: boolean = false)
{
let als: AlignedDimension[] = [];
let foots: number[] = [];
let minY: number = Infinity;
let minZ: number = Infinity;
let maxZ: number = -Infinity;
let drawCSInv = new Matrix4().getInverse(drawCS);
for (let br of brs)
{
let mtx = new Matrix4().multiplyMatrices(drawCSInv, br.OCS);
let box = br.BoundingBoxInOCS.applyMatrix4(mtx);
foots.push(box.min.x, box.max.x);
minY = Math.min(minY, box.min.y);
minZ = Math.min(minZ, box.min.z);
maxZ = Math.max(maxZ, box.max.z);
}
tool.EnableCabinetInsideHeight = store.m_Option.inH;
tool.EnableCabinetInsideWidth = store.m_Option.inW;
arraySortByNumber(foots);
arrayRemoveDuplicateBySort(foots, equalnn(1));
tool.EnableDimAllSize = store.m_Option.total;
tool.EnableFrontOutDims = store.m_Option.out;
let drawY = minY - 20;
let armY = drawY - 90;
let z = useMaxZ ? maxZ : minZ;
tool.EnableFilterSmallDim = store.m_Option.noSmSize;
tool.EnableFilterAppointDimSize = store.m_Option.noAppointSize;
let maxOffsetY = 0;
//draw
for (let i = 0; i < foots.length - 1; i++)
{
let x1 = foots[i];
let x2 = foots[i + 1];
let alDim = new AlignedDimension(
new Vector3(x1, drawY, z),
new Vector3(x2, drawY, z),
new Vector3(x1, armY, z),
new Vector3(x2, armY, z),
);
if (!equaln(textRotation, 0) && textRotation)
alDim.TextRotation = textRotation;
alDim.DefaultValue = { offset: new Vector2(-30, -72), isFlipped: isLeadOutFlipped };
alDim.ApplyMatrix(drawCS);
if (needJig)
JigUtils.Draw(alDim);
else
app.Database.ModelSpace.Append(alDim);
if (i > 0)
{
let box = alDim.Text.BoundingBox;
//找前4个标注 如果有碰撞就提高一个身位
let q4gAl = als.length > 4 ? als.slice(als.length - 4) : als;//前4个
let lastAl = als[als.length - 1];//前1个标注
for (let al of q4gAl)
{
if (al.Text.BoundingBox.intersectsBox(box))
{
alDim.LeadOutOffsetX += lastAl.LeadOutOffsetX;
alDim.LeadOutOffsetY += lastAl.LeadOutOffsetY;
break;
}
}
if (Math.abs(alDim.LeadOutOffsetY) > maxOffsetY)
maxOffsetY = alDim.LeadOutOffsetY;
}
als.push(alDim);
}
tool.FilterSmallDimSize = store.m_Option.noShowMinSize;
//draw总长标注 需要拖拽的FastDim不需要总长 仅有一块板时不需要总长
let drawYTotal = minY - 230 + maxOffsetY;
let armYTotal = drawYTotal - 80 + (maxOffsetY / 2);
tool.FiltereCabinetInsideSmallDim = store.m_Option.noInSize;
tool.EanbleCabinetInsideSmallDimSize = store.m_Option.noShowMinInSize;
if (!needJig && brs.length > 1)
{
let alDimTotal = new AlignedDimension(
new Vector3(foots[0], drawYTotal, z),
new Vector3(foots[foots.length - 1], drawYTotal, z),
new Vector3(foots[0], armYTotal, z),
new Vector3(foots[foots.length - 1], armYTotal, z)
);
if (textRotation)
alDimTotal.TextRotation = textRotation;
alDimTotal.LeadOutFlipped = isLeadOutFlipped;
alDimTotal.ApplyMatrix(drawCS);
als.push(alDimTotal);
app.Database.ModelSpace.Append(alDimTotal);
}
if (tool.EnableFilterAppointDimSize && store.m_Option.noShowAppointSizes !== '')
for (let str of store.m_Option.noShowAppointSizes.split(','))
for (let str2 of str.split(' '))
for (let str3 of str2.split('|'))
tool.FilterDimSizeSet.add(str3);
return als;
tool.Do(brs);
}
}
/**
*Board[]
*
* @param {Entity[]} oldBoard
* @return {*} {Board[]}
* @memberof Command_AutoDimBrs
*
*/
backBoards(oldBoard: Entity[]): Board[]
GetAllBoards(ents: Entity[], outAllBrs = [], parentOCS: Matrix4 = undefined, parentSCS: Matrix4 = undefined): Board[]
{
let newBoards: Board[] = [];
for (let en of oldBoard)
for (let en of ents)
{
if (en instanceof Board)
newBoards.push(en);
outAllBrs.push(en);
else if (en instanceof HardwareCompositeEntity)
{
if (IsHandle(en)) continue; //过滤把手五金
let hardwareCompositeEntitys = this.backBoards(en.GetAllEntity());
for (let hce of hardwareCompositeEntitys)
newBoards.push(hce);
}
else
continue;
}
return newBoards;
}
}
if (IsHandle(en) || IsHinge(en)) continue; //拉手 铰链
//只是用来保存配置
class AutoDimBrsStore implements IConfigStore
{
configName = "默认";
configsNames = ['默认'];
config = {
option: {
dimType: 3
if (IsDoor(en))//如果是门,就给他一个虚拟板
{
let box = en.BoundingBoxInOCS;
let size = box.getSize(new Vector3);
let br = Board.CreateBoard(size.z, size.x, size.y, BoardType.Behind);
if (!equalv3(box.min, ZeroVec))
br.ApplyMatrix(MoveMatrix(box.min.sub(br.BoundingBox.min)));
br.ApplyMatrix(en.OCSNoClone);
br.SpaceOCS = en.SpaceCSNoClone;
// TestDraw(br);
outAllBrs.push(br);
}
};
InitOption()
else if (en.HardwareOption.isSplite)//理论上应该拆解的才应该分裂
{
let curOCS = en.OCSNoClone;
if (parentOCS) curOCS = new Matrix4().multiplyMatrices(parentOCS, curOCS);
parentSCS = parentSCS ?? en.SpaceCSNoClone;
for (let e of en.Entitys)
{
if (e instanceof Board)
{
this.config = {
option: {
dimType: 3
let newBr = e.Clone();//拷贝一个板来更新到外部
newBr.ApplyMatrix(curOCS);
newBr.SpaceOCS = parentSCS;
outAllBrs.push(newBr);
// TestDraw(newBr);
}
};
else if (e instanceof HardwareCompositeEntity)
this.GetAllBoards([e], outAllBrs, curOCS, parentSCS);
}
SaveConfig()
{
return this.config;
}
UpdateOption(conf: IConfigOption<any>)
{
Object.assign(this.config, conf);
}
}
return outAllBrs;
}
}

@ -0,0 +1,60 @@
import { observable, toJS } from "mobx";
import { DefaultAutoDimBrsOption } from "../../Editor/DefaultConfig";
import { BoardModalType } from "../../UI/Components/Board/BoardModalType";
import { IConfigOption } from "../../UI/Components/Board/UserConfig";
import { IAutoDimBrsOption } from "../../UI/Store/BoardInterface";
import { IConfigStore } from "../../UI/Store/BoardStore";
import { userConfigStore } from "../../UI/Store/UserConfigStore";
export class AutoDimBrsStore implements IConfigStore
{
@observable configName = "默认";
@observable configsNames: string[] = [];
@observable m_Option: IAutoDimBrsOption = { ...DefaultAutoDimBrsOption };
InitOption()
{
Object.assign(this.m_Option, DefaultAutoDimBrsOption);
}
InitConfigs()
{
let config: IConfigOption = {};
config.option = toJS(this.m_Option);
let configs: { [key: string]: IConfigOption; } = {};
configs["默认"] = config;
return configs;
}
SaveConfig()
{
//新的配置
let newConfig: IConfigOption = {};
newConfig.option = toJS(this.m_Option);
return newConfig;
};
UpdateOption(conf: IConfigOption<any>)
{
if (!conf.option)
{
this.InitOption();
let config = this.InitConfigs();
userConfigStore.InitConfigs(config, BoardModalType.AutoDimBrs);
return;
}
Object.assign(this.m_Option, conf.option);
}
private static _SingleInstance: AutoDimBrsStore;
static GetInstance(): AutoDimBrsStore
{
if (this._SingleInstance) return this._SingleInstance;
this._SingleInstance = new AutoDimBrsStore;
return this._SingleInstance;
}
}
export const autoDimBrsStore = AutoDimBrsStore.GetInstance();

@ -1,520 +1,12 @@
import { Box3, Intersection, MathUtils, Matrix4, Object3D, Raycaster, Vector2, Vector3 } from "three";
import { app } from "../../ApplicationServices/Application";
import { arrayRemoveDuplicateBySort, arrayRemoveIf, arraySortByNumber } from "../../Common/ArrayExt";
import { FixedNotZero } from "../../Common/Utils";
import { AlignedDimension } from "../../DatabaseServices/Dimension/AlignedDimension";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Curve } from "../../DatabaseServices/Entity/Curve";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Region } from "../../DatabaseServices/Entity/Region";
import { Raycast } from "../../Editor/PointPick";
import { Box3Ext } from "../../Geometry/Box";
import { CoordinateSystem } from "../../Geometry/CoordinateSystem";
import { equaln, equalnn, isParallelTo, XAxis, YAxis, ZAxis } from "../../Geometry/GeUtils";
import { OBB } from "../../Geometry/OBB/obb";
import { SurroundOutlineParse } from "../../Geometry/SpaceParse/SurroundOutlineParse";
import { BoolOpeartionType } from "../../GraphicsSystem/BoolOperateUtils";
import { RenderType } from "../../GraphicsSystem/RenderType";
import { BoardType } from "../../UI/Store/BoardInterface";
import { ViewChange } from "../ViewChange";
export enum EDimType
{
Total = 0b000001,
Out = 0b000010,
InW = 0b000100,
InH = 0b001000,
NoRepeat = 0b010000,
NoSmSize = 0b100000,
All = ~(~0 << 7)
}
interface DirPls
{
left: Curve[];
right: Curve[];
top: Curve[];
bottom: Curve[];
Total = "total",//整体标注
Out = "out",//柜外标注(前视图标注)
InW = "inW",//柜内宽标注
InH = "inH",//柜内高标注
NoRepeat = "noRepeat",//删除重复
NoSmSize = "noSmSize",//过滤小尺寸
NoAppointSize = "noAppointSize",//过滤指定尺寸
NoInSize = "noInSize",//空间小于该数值时 不标注内空
}
interface DirBrs
{
left: Board[];
right: Board[];
top: Board[];
bottom: Board[];
}
const DEG90 = 90;//90°
export class AutoDimBoardsTool
{
private qsMtx = new Matrix4().makeBasis(XAxis, ZAxis, YAxis.clone().negate());
private min = new Vector3();
private maxThickness = 0;
private type: EDimType;
private repeatDim = new Set<string>();
Do(boardList: Board[], type: EDimType)
{
this.repeatDim.clear();
this.type = type;
this.maxThickness = 0;
arrayRemoveIf(boardList, b =>
{
this.maxThickness = Math.max(this.maxThickness, b.Thickness);
return !equaln(MathUtils.radToDeg(b.Rotation.x) % (DEG90), 0)
|| !equaln(MathUtils.radToDeg(b.Rotation.y) % (DEG90), 0)
|| !equaln(MathUtils.radToDeg(b.Rotation.z) % (DEG90), 0);
});
//原数据转二维数组[[br0],[br1],[br2],[br3],[br4]...],并记录每组的Box
let brBoxs: Box3Ext[] = [];
let brGroups: Board[][] = boardList.map(item =>
{
this.maxThickness = Math.max(this.maxThickness, item.Thickness);
brBoxs.push(item.BoundingBox);
return [item];
});
for (let i = 0; i < brGroups.length; i++)
{
for (let j = i + 1; j < brGroups.length; j++)
{
//如有合并则重新开始
if (brBoxs[i].intersectsBox(brBoxs[j], 50)) //柜体间隙在50单位内算一个整体
{
brGroups[i] = [...brGroups[i], ...brGroups[j]];
brBoxs[i].union(brBoxs[j]);
brGroups.splice(j, 1);
brBoxs.splice(j, 1);
i = -1;
break;
}
}
}
for (let i = 0; i < brGroups.length; i++)
{
this.TotalDim(brBoxs[i]);
const brs = brGroups[i];
this.DimOut(brs);
if ((type & EDimType.InW) || (type & EDimType.InH))
this.DimIn(brs);
}
}
private TotalDim(box: Box3)
{
let p1 = box.min;
this.min.copy(p1);
if (this.type & EDimType.Total)
{
let p2 = new Vector3(box.min.x, box.max.y, box.min.z);
let dir = ZAxis.clone().multiplyScalar(-2);
dir.copy(new Vector3(-10));
let dim3 = new AlignedDimension();
dim3.FootP1 = p1.clone().add(dir);
dim3.FootP2 = p2.clone().add(dir);
dir.multiplyScalar(20);
dim3.ArmP1 = p1.clone().add(dir);
dim3.ArmP2 = p2.clone().add(dir);
app.Database.ModelSpace.Append(dim3);
}
return;
// let dim1 = new AlignedDimension();
// dim1.ApplyMatrix(mat);
// let dir = ZAxis.clone().multiplyScalar(-2);
// dim1.FootP1 = p1.clone().add(dir);
// dim1.FootP2 = p2.clone().add(dir);;
// dir = ZAxis.clone().multiplyScalar(-200);
// dim1.ArmP1 = p1.clone().add(dir);
// dim1.ArmP2 = p2.clone().add(dir);
// app.Database.ModelSpace.Append(dim1);
// let dim2 = new AlignedDimension();
// dim2.ApplyMatrix(mat);
// dir.copy(new Vector3(-10));
// dim2.FootP1 = p1.clone().add(dir);
// dim2.FootP2 = p3.clone().add(dir);
// dir.multiplyScalar(10);
// dim2.ArmP1 = p1.clone().add(dir);
// dim2.ArmP2 = p3.clone().add(dir);
// app.Database.ModelSpace.Append(dim2);
// dir.copy(new Vector3(10));
// let dim3 = new AlignedDimension();
// dim3.FootP1 = p2.clone().add(dir);
// dim3.FootP2 = p4.clone().add(dir);
// dir.multiplyScalar(10);
// dim3.ArmP1 = p2.clone().add(dir);
// dim3.ArmP2 = p4.clone().add(dir);
// app.Database.ModelSpace.Append(dim3);
}
DimOut(brs: Board[])
{
this.DrawFrontDim(brs, -Math.PI);
}
private DimIn(brs: Board[])
{
let bsMap = new Map<BoardType, Board[]>();
for (let br of brs)
{
if (bsMap.has(br.BoardType))
{
bsMap.get(br.BoardType).push(br);
}
else
{
bsMap.set(br.BoardType, [br]);
}
}
let layers = bsMap.get(BoardType.Layer) ?? [];
let vertials = bsMap.get(BoardType.Vertical) ?? [];
layers.sort((b1, b2) => b1.Position.z - b2.Position.z);
vertials.sort((b1, b2) => b1.Position.x - b2.Position.x);
if (this.type & EDimType.InH)
this.DimInBy(layers, vertials, true);
if (this.type & EDimType.InW)
this.DimInBy(vertials, layers, false);
}
private RayPoint(p: Vector3, n: Vector3, brs: Object3D[]): Intersection
{
let ray = new Raycaster(p, n);
let intersection = Raycast(ray, brs);
return intersection;
}
private DimInBy(bs: Board[], bs2: Board[], isVertial: boolean)
{
let cache = new Set<Object3D>();
let ptss: [Vector3, Vector3][] = [];
let brObjects = bs.map(b => b.GetDrawObjectFromRenderType(RenderType.Physical));
let allObjects = [...brObjects];
let dir = isVertial ? ZAxis : XAxis;
let dirInv = dir.clone().negate();
for (let i = 0; i < bs.length; i++)
{
let br = bs[i];
let nor = br.Normal;
let obj = brObjects.shift();
let intPtsY: number[] = [];
const position = br.Position;
for (let j = 0; j < bs2.length; j++)
{
let br2 = bs2[j];
if (isVertial)
{
if (br2.Position.z <= position.z)
continue;
}
else
{
if (br2.Position.x <= position.x) continue;
}
let p = new Vector3(br2.Width / 2, 0, br2.Thickness / 2).applyMatrix4(br2.OCS);
let intersection = this.RayPoint(p, dirInv, allObjects);
if (intersection && intersection.object && intersection.object === obj)
{
intPtsY.push(p.applyMatrix4(br.OCSInv).y);
}
}
intPtsY.sort((a, b) => a - b);
intPtsY.unshift(0);
intPtsY.push(br.Height);
let center = new Vector3();
cache.clear();
for (let j = 0; j < intPtsY.length - 1; j++)
{
let y1 = intPtsY[j];
let y2 = intPtsY[j + 1];
if (Math.abs(y2 - y1) < 50) continue;
center.set(br.Width / 2, (y1 + y2) / 2, br.Thickness - 1).applyMatrix4(br.OCS);
let intersection = this.RayPoint(center, dir, brObjects);
if (intersection
&& intersection.object
&& !cache.has(intersection.object)
&& intersection.distance > 50)
{
cache.add(intersection.object);
ptss.push([center.clone().add(nor), intersection.point]);
}
}
}
for (let ps of ptss)
{
let dim = new AlignedDimension();
dim.ApplyMatrix(this.qsMtx);
if (!isVertial && this.type & EDimType.InH)
{
ps[0].z += 100;
ps[1].z += 100;
}
dim.FootP1 = ps[0];
dim.FootP2 = ps[1];
if (!this.handleRepeat(ps[0], ps[1]))
continue;
dim.ArmP1 = ps[0].setY(this.min.y + 50);
dim.ArmP2 = ps[1].setY(this.min.y + 50);
app.Database.ModelSpace.Append(dim);
}
}
async DrawFrontDim(brs: Board[], textRo: number)
{
//构造绘制坐标
let spaceOcs = brs[0].SpaceOCS;
let cs = new CoordinateSystem().CopyForm(spaceOcs);
let revX = cs.XAxis.clone().negate();
let revY = cs.YAxis.clone().negate();
let revZ = cs.ZAxis.clone().negate();
let drawCS_right = new Matrix4()
.makeBasis(revZ, revX, revY)
.copyPosition(spaceOcs);
let drawCS_left = new Matrix4()
.makeBasis(cs.ZAxis, cs.XAxis, revY)
.copyPosition(spaceOcs);
let drawCS_top = new Matrix4()
.makeBasis(revX, revZ, revY)
.copyPosition(spaceOcs);
let drawCS_bottom = new Matrix4()
.makeBasis(cs.XAxis, cs.ZAxis, revY)
.copyPosition(spaceOcs);
//获得外轮廓
let viewDir = cs.YAxis;
let oldUCS = app.Editor.UCSMatrix;
let viewChange = new ViewChange(viewDir);
viewChange.UcsLookAt(viewDir);
let spaceParse = new SurroundOutlineParse(brs);
await spaceParse.Parse();
let outlineParseUCS = app.Editor.UCSMatrixInv;
app.Editor.UCSMatrix = oldUCS;
if (spaceParse.Polylines.length === 0)
return;
let pls = this.GetOutLineByBoolUnion(spaceParse.Polylines);
let outlinesBox = new Box3();
spaceParse.Outlines.forEach((ol) => { outlinesBox.union(ol.BoundingBox); });
pls.forEach((pl) =>
{
pl.CloseMark = true;
pl.OCS = spaceParse.Outlines[0].OCS;
let moveMatrix = new Matrix4().setPosition(outlinesBox.min.clone().sub(pl.BoundingBox.min));
pl.ApplyMatrix(moveMatrix);
});
//分析外轮廓上下左右并得到上下左右的板件
let dirPls = this.JudgeOutlineDirection(pls, cs);
let dirBrs: DirBrs = { right: [], left: [], top: [], bottom: [] };
for (let key in dirPls)
{
for (let i = 0; i < dirPls[key].length; i++)
{
let l = dirPls[key][i] as Curve;
let xv = l.EndPoint.sub(l.StartPoint);
let zv = viewDir;
let yv = zv.clone().cross(xv);
let ocs = new Matrix4().makeBasis(xv.normalize(), yv.negate().normalize(), zv.normalize());
ocs.setPosition(l.StartPoint);
let cuObb = new OBB(ocs, new Vector3(l.Length, this.maxThickness || 20, this.maxThickness || 20).multiplyScalar(0.5));
let filterFunc = (b: Board) =>
{
if (!dirBrs[key].includes(b))
if (cuObb.intersectsOBB(b.OBB, true, outlineParseUCS))
return true;
return false;
};
dirBrs[key].push(...brs.filter(filterFunc));
}
}
let als: AlignedDimension[] = [];
//绘制标注
if (dirBrs.bottom.length > 0) als.push(...this.DrawDim(dirBrs.bottom, drawCS_bottom, undefined, true, true));
if (dirBrs.right.length > 0) als.push(...this.DrawDim(dirBrs.right, drawCS_right, textRo, true, true));
if (dirBrs.top.length > 0) als.push(...this.DrawDim(dirBrs.top, drawCS_top, textRo, true));
if (dirBrs.left.length > 0) als.push(...this.DrawDim(dirBrs.left, drawCS_left, textRo, true));
return als;
}
/**
*
* @param brs
* @param drawCS
*/
DrawDim(brs: Board[], drawCS: Matrix4, textRotation?: number, useMaxZ: boolean = false, isLeadOutFlipped: boolean = false)
{
let als: AlignedDimension[] = [];
let foots: number[] = [];
let minY: number = Infinity;
let minZ: number = Infinity;
let maxZ: number = -Infinity;
let drawCSInv = new Matrix4().getInverse(drawCS);
for (let br of brs)
{
let mtx = new Matrix4().multiplyMatrices(drawCSInv, br.OCS);
let box = br.BoundingBoxInOCS.applyMatrix4(mtx);
foots.push(box.min.x, box.max.x);
minY = Math.min(minY, box.min.y);
minZ = Math.min(minZ, box.min.z);
maxZ = Math.max(maxZ, box.max.z);
}
arraySortByNumber(foots);
arrayRemoveDuplicateBySort(foots, equalnn(1));
let drawY = minY - 20;
let armY = drawY - 90;
let z = useMaxZ ? maxZ : minZ;
let maxOffsetY = 0;
//draw
if (this.type & EDimType.Out)
for (let i = 0; i < foots.length - 1; i++)
{
let x1 = foots[i];
let x2 = foots[i + 1];
if (x2 - x1 < 50 && (this.type & EDimType.NoSmSize)) continue;
let alDim = new AlignedDimension(
new Vector3(x1, drawY, z),
new Vector3(x2, drawY, z),
new Vector3(x1, armY, z),
new Vector3(x2, armY, z),
);
if (!equaln(textRotation, 0) && textRotation)
alDim.TextRotation = textRotation;
alDim.DefaultValue = { offset: new Vector2(-30, -72), isFlipped: isLeadOutFlipped };
alDim.ApplyMatrix(drawCS);
if (!this.handleRepeat(alDim.FootP1, alDim.FootP2))
continue;
app.Database.ModelSpace.Append(alDim);
if (i > 0)
{
let box = alDim.Text.BoundingBox;
//找前4个标注 如果有碰撞就提高一个身位
let q4gAl = als.length > 4 ? als.slice(als.length - 4) : als;//前4个
let lastAl = als[als.length - 1];//前1个标注
for (let al of q4gAl)
{
if (al.Text.BoundingBox.intersectsBox(box))
{
alDim.LeadOutOffsetX += lastAl.LeadOutOffsetX;
alDim.LeadOutOffsetY += lastAl.LeadOutOffsetY;
break;
}
}
if (Math.abs(alDim.LeadOutOffsetY) > maxOffsetY)
maxOffsetY = alDim.LeadOutOffsetY;
}
als.push(alDim);
}
//draw总长标注 需要拖拽的FastDim不需要总长 仅有一块板时不需要总长
let drawYTotal = minY + maxOffsetY;
if (this.type & EDimType.Out)
drawYTotal -= 23;
let armYTotal = drawYTotal - 80 + (maxOffsetY / 2);
if (brs.length > 0 && (this.type & EDimType.Total))
{
let alDimTotal = new AlignedDimension(
new Vector3(foots[0], drawYTotal, z),
new Vector3(foots[foots.length - 1], drawYTotal, z),
new Vector3(foots[0], armYTotal, z),
new Vector3(foots[foots.length - 1], armYTotal, z)
);
if (textRotation)
alDimTotal.TextRotation = textRotation;
alDimTotal.LeadOutFlipped = isLeadOutFlipped;
alDimTotal.ApplyMatrix(drawCS);
als.push(alDimTotal);
if (this.handleRepeat(alDimTotal.FootP1, alDimTotal.FootP2))
app.Database.ModelSpace.Append(alDimTotal);
}
return als;
}
/**
*
* @param pl 线
* @param cs
* @memberof Command_AutoDimBrs
*/
JudgeOutlineDirection(pls: Polyline[], cs: CoordinateSystem): DirPls
{
let res: DirPls = { right: [], left: [], top: [], bottom: [] };
for (let pl of pls)
{
let clockWise = pl.Area2 < 0;//true为顺时针 false为逆时针
for (let i = 0; i < pl.EndParam; i++)
{
let cu = pl.GetCurveAtParam(i);
let derv = cu.GetFistDeriv(0).normalize();
if (isParallelTo(derv, cs.XAxis))
{
if (derv.dot(cs.XAxis) > 0)
clockWise ? res.top.push(cu) : res.bottom.push(cu);
else
clockWise ? res.bottom.push(cu) : res.top.push(cu);
}
else
{
if (derv.dot(cs.ZAxis) < 0)
clockWise ? res.right.push(cu) : res.left.push(cu);
else
clockWise ? res.left.push(cu) : res.right.push(cu);
}
}
}
return res;
}
/**
*
* @memberof Command_AutoDimBrs
*/
private GetOutLineByBoolUnion(pls: Polyline[])
{
let reg = Region.CreateFromCurves([pls.shift()]);
for (let pl of pls)
reg.BooleanOper(Region.CreateFromCurves([pl]), BoolOpeartionType.Union);
let plsRes = reg.ShapeManager.ShapeList.map(s => s.Outline.Curve) as Polyline[];
return plsRes;
}
private handleRepeat(p0: Vector3, p1: Vector3)
{
let distance = FixedNotZero(p0.distanceTo(p1));
if (this.repeatDim.has(distance) && (this.type & EDimType.NoRepeat))
return false;
this.repeatDim.add(distance);
return true;
}
}
export const autoDimBoardTool = new AutoDimBoardsTool();

@ -16,7 +16,7 @@ export class BreakDimAligen extends BreakDimTool
protected CloneDimension(dim: AlignedDimension): AlignedDimension
{
let ndim = dim.Clone() as AlignedDimension;
this.m_BasePoint = dim.FootP2;
this._BasePoint = dim.FootP2;
if (!this.m_line)
this.m_line = new Line(dim.ArmP1, dim.ArmP2);
if (!this.f_line)
@ -31,7 +31,7 @@ export class BreakDimAligen extends BreakDimTool
*/
protected UpdateNextPoint(p: Vector3, ndim1: AlignedDimension, ndim2: AlignedDimension)
{
let last = this.CloneDimension(this.m_LastDim as AlignedDimension);
let last = this.CloneDimension(this._LastDim as AlignedDimension);
let { closestPt, param } = this.m_line.GetClosestAtPoint(p, true);
if (param <= 1 && param >= 0)

@ -8,21 +8,21 @@ import { PromptStatus } from "../../Editor/PromptResult";
import { Dimension } from "./Command_DimContinue";
export class BreakDimTool
{
protected m_LastDim: Dimension;
protected m_BasePoint: Vector3;
protected _LastDim: Dimension;
protected _BasePoint: Vector3;
//开始绘制.
async StartDraw(lastDim: Dimension)
{
this.m_LastDim = lastDim.Clone();
this._LastDim = lastDim.Clone();
let oldUcs = app.Editor.UCSMatrix;
app.Editor.UCSMatrix = this.m_LastDim.OCS;
let newDim1 = this.CloneDimension(this.m_LastDim) as AlignedDimension | LineAngularDimension;
let newDim2 = this.CloneDimension(this.m_LastDim) as AlignedDimension | LineAngularDimension;
app.Editor.UCSMatrix = this._LastDim.OCS;
let newDim1 = this.CloneDimension(this._LastDim) as AlignedDimension | LineAngularDimension;
let newDim2 = this.CloneDimension(this._LastDim) as AlignedDimension | LineAngularDimension;
if (newDim1 instanceof AlignedDimension && newDim2 instanceof AlignedDimension)
{
newDim1.LeadOutFlipped = true;
newDim2.LeadOutFlipped = false;
newDim1.LeadInLeft = true;
newDim2.LeadInLeft = false;
}
lastDim.Visible = false;
@ -31,7 +31,7 @@ export class BreakDimTool
let ptRes = await app.Editor.GetPoint({
AllowNone: true,
BasePoint: this.m_BasePoint,
BasePoint: this._BasePoint,
Msg: "指定断点原点",
Callback: p => this.UpdateNextPoint(p, newDim1, newDim2)
});
@ -84,7 +84,7 @@ export class BreakDimTool
*/
protected EndDraw()
{
this.m_LastDim.GoodBye();
this._LastDim.GoodBye();
}
/**
* :,

@ -0,0 +1,707 @@
import { Box3, MathUtils, Matrix4, Vector2, Vector3 } from "three";
import { arrayLast, arrayRemoveDuplicateBySort, arrayRemoveIf, arraySortByNumber } from "../../Common/ArrayExt";
import { Draw } from "../../Common/Draw";
import { AlignedDimension } from "../../DatabaseServices/Dimension/AlignedDimension";
import { Arc } from "../../DatabaseServices/Entity/Arc";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Curve } from "../../DatabaseServices/Entity/Curve";
import { Entity } from "../../DatabaseServices/Entity/Entity";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Region } from "../../DatabaseServices/Entity/Region";
import { TemplateRecord } from "../../DatabaseServices/Template/TemplateRecord";
import { AsVector2, equaln, equalnn, isParallelTo, isPerpendicularityTo, midPoint, ZAxis } from "../../Geometry/GeUtils";
import { OBB } from "../../Geometry/OBB/obb";
import { BoolOpeartionType } from "../../GraphicsSystem/BoolOperateUtils";
import { TestDraw } from "../test/TestUtil";
const TEST_DRAW_CURVE = false;
/**
* :autodimbrs
* ,
*/
export class DimBoards
{
//#region UI设置 应该应用到这里来
EnableDimAllSize = true;//整体标注 (全长全宽全高)
EnableFrontOutDims = true;//柜外标注 (前视图的详细外圈标注)
EnableCabinetInsideWidth = true;//柜内宽
EnableCabinetInsideHeight = true;//柜内高
EnableFilterSmallDim = true;//过滤小尺寸
FilterSmallDimSize = 50;//过滤小尺寸的最小尺寸
EnableFilterAppointDimSize = true;
FilterDimSizeSet = new Set<string>();//过滤指定尺寸列表
EnableFrontIgnoreBackBoard = true;//在前视图标注时忽略背板
EanbleParseGroups = true;//如果不解析分堆,则只有一个堆
FiltereCabinetInsideSmallDim = true;//柜内空间小于150时不标注
EanbleCabinetInsideSmallDimSize = 300;
//#endregion
private groups: (Board[])[] = [];
private groupsBoxs: Box3[] = [];//box in spacecs
private boardBoxMap = new Map<Board, Box3>();//box in spacecs
constructor(
)
{
}
Do(brs: Board[])
{
this.ParseBoardGroups(brs);
this.DoDim();
}
/**
* (+)
* (1:,2)
*/
private ParseBoardGroups(brs: Board[])
{
brs = brs.filter(FilterDimBoardFn);
while (brs.length)
{
let group = [brs.pop()];
let spaceCSInv = group[0].SpaceOCSInv;
let box = group[0].GetBoundingBoxInMtx(spaceCSInv);
this.groupsBoxs.push(box);
this.boardBoxMap.set(group[0], box.clone());
for (let i = 0; i < group.length; i++)
{
let br = group[i];
//模块内所有实体成一组
let templateAllEnts: Set<Entity>;
if (br.Template?.Object)
{
let template = br.Template.Object as TemplateRecord;
templateAllEnts = new Set(template.Root.AllEntitys);
}
else
templateAllEnts = new Set;
arrayRemoveIf(brs, _br =>
{
let _box = _br.GetBoundingBoxInMtx(spaceCSInv);
if (!this.EanbleParseGroups || templateAllEnts.has(_br) || box.intersectsBox(_box, 50))
{
box.union(_box);
group.push(_br);
this.boardBoxMap.set(_br, _box);
return true;
}
return false;
});
}
this.groups.push(group);
}
}
private DoDim()
{
for (let i = 0; i < this.groups.length; i++)
{
let brs = this.groups[i];
let groupSpaceBox = this.groupsBoxs[i];
let spaceCS = brs[0].SpaceOCS;
let x = new Vector3().setFromMatrixColumn(spaceCS, 0);
let y = new Vector3().setFromMatrixColumn(spaceCS, 1);
let z = new Vector3().setFromMatrixColumn(spaceCS, 2);
let spaceFrontCS = new Matrix4().makeBasis(x, z, y.negate()).copyPosition(spaceCS);
let spaceFrontCSInv = new Matrix4().getInverse(spaceFrontCS);
const offsetYDist = 130;//标注线距离柜子的距离
let backReg = new Region;//背板面域
let lcReg = new Region;//立板层板面域
//板件轮廓
for (let br of brs)
{
let normal = br.Normal;
let brBox = this.boardBoxMap.get(br);
if (isParallelTo(normal, y))
{
let cu = br.ContourCurve.Clone().ApplyMatrix(br.OCS.premultiply(spaceFrontCSInv));
cu.Z0();
backReg.BooleanOper(Region.CreateFromCurves([cu]), BoolOpeartionType.Union);
}
else
{
let pl = new Polyline().RectangleFrom2Pt(new Vector3(brBox.min.x, brBox.min.z), new Vector3(brBox.max.x, brBox.max.z));
lcReg.BooleanOper(Region.CreateFromCurves([pl]), BoolOpeartionType.Union);
}
}
//并集
let reg = backReg.Clone();
reg.BooleanOper(lcReg.Clone(), BoolOpeartionType.Union);
//可能有多个吗?
let pls = reg.ShapeManager.ShapeList.map(s => s.Outline.Curve) as Polyline[];
//#region 炸开 分析上下左右区域?
let leftCurves: Curve[] = [];
let rightCurves: Curve[] = [];
let topCurves: Curve[] = [];
let downCurves: Curve[] = [];
for (let pl of pls)
{
let dir = Math.sign(pl.Area2);
for (let c of pl.Explode())
{
let derv = c.GetFistDeriv(0).multiplyScalar(dir);
if (Math.abs(derv.x) > Math.abs(derv.y))
{
if (derv.x > 0)
downCurves.push(c);
else
topCurves.push(c);
}
else
{
if (derv.y > 0)
rightCurves.push(c);
else
leftCurves.push(c);
}
}
}
//#endregion
//所有的脚点(在内空标注时,避免重复)
let alldimkeys: (Set<string>)[] = [];
let alldims: (AlignedDimension[])[] = [];
//#region 外圈标注(前视图)
let startXY = [groupSpaceBox.min.z, groupSpaceBox.max.z, groupSpaceBox.min.x, groupSpaceBox.max.x];//未来某天我们如果改成通用的算法,应该修改这里
let dirCurves = [downCurves, topCurves, leftCurves, rightCurves];
let preFoots: number[];
for (let j = 0; j < 4; j++)
{
//解析相交的板
let cus = dirCurves[j];
let dirBrs: Board[] = [];//该方向上有交集的板
for (let c of cus)
{
let _x = c.GetFistDeriv(0).normalize();
let _z = ZAxis;
let _y = new Vector3().crossVectors(_z, _x);
let ocs = new Matrix4().makeBasis(_x, _y, _z).setPosition(c.StartPoint.setZ(-5000))
.premultiply(spaceFrontCS);
let cuObb = new OBB(ocs, new Vector3(c.Length, 20, 10000));
for (let br of brs)
{
if (this.EnableFrontIgnoreBackBoard && isParallelTo(br.Normal, y))
continue;
if (cuObb.intersectsOBB(br.OBB))
dirBrs.push(br);
}
if (TEST_DRAW_CURVE)//测试绘制轮廓曲线
{
let cc = c.Clone();
cc.Move({ x: 0, y: 0, z: 100 });
cc.ApplyMatrix(spaceFrontCS);
TestDraw(cc, j + 1);
}
}
//解析相交的板end
let dims = new Set<string>;
alldimkeys.push(dims);
let als: AlignedDimension[] = [];
alldims.push(als);
//解析脚点
let xIndex = Math.floor(j / 2);//x y 0 1
let yIndex = Math.abs(xIndex - 1);
let foots: number[] = [];
for (let br of dirBrs)
{
let brbox = this.boardBoxMap.get(br);
foots.push(brbox.min.getComponent(xIndex * 2), brbox.max.getComponent(xIndex * 2));//y->z轴
}
arraySortByNumber(foots);
arrayRemoveDuplicateBySort(foots, equalnn(1));
let preF = preFoots;
if (preFoots)
{
preFoots = undefined;
if (preF.every((v, i) => equaln(v, foots[i])))
continue;
}
else
preFoots = foots;
//解析脚点end
//没有允许标注前视图的尺寸
if (!this.EnableFrontOutDims) continue;
//生成标注
let start = startXY[j];//y轴开始位置
let signDir = Math.sign((j % 2) - 0.5);//-1 1 -1 1 下上左右
for (let k = 0; k < foots.length - 1; k++)
{
let x1 = foots[k];//假设是x 其实可能是y
let x2 = foots[k + 1];
if (preF && (preF.findIndex(x => (equaln(x, x2))) - preF.findIndex(x => (equaln(x, x1))) === 1))
continue;
//过滤小尺寸
if (this.EnableFilterSmallDim && (x2 - x1) < this.FilterSmallDimSize) continue;
let f1 = new Vector3().setComponent(xIndex, x1).setComponent(yIndex, start);
let f2 = new Vector3().setComponent(xIndex, x2).setComponent(yIndex, start);
let a1 = f1.clone().setComponent(yIndex, start + signDir * offsetYDist);
let a2 = f2.clone().setComponent(yIndex, start + signDir * offsetYDist);
let alDim = new AlignedDimension(f1, f2, a1, a2);
alDim.ApplyMatrix(spaceFrontCS);
als.push(alDim);
dims.add(`${x1.toFixed(3)},${x2.toFixed(3)}`);
//过滤尺寸集(我们还是保留这个标注 以便标注避让的时候正常工作.只是我们不再画它)
if (this.EnableFilterAppointDimSize && this.FilterDimSizeSet.has(alDim.TextString))
alDim.Visible = false;
else
Draw(alDim);
}
//生成标注end
//标注避让(从左往右扫略的思路)
DimBoards.DimAvoid(foots, als, j);
//标注避让end
}
//#endregion
if (this.EnableCabinetInsideHeight || this.EnableCabinetInsideWidth)
{
//#region 内空标注
// TestDraw(backReg.Clone(), 3);
// TestDraw(lcReg.Clone(), 1);
backReg.BooleanOper(lcReg, BoolOpeartionType.Subtract);
// TestDraw(backReg.Clone(), 1);
for (let shape of (backReg.ShapeManager.ShapeList))
{
let pl = shape.Outline.Curve as Polyline;
let opls = pl.GetOffsetCurves(Math.sign(pl.Area2) * -(this.FiltereCabinetInsideSmallDim ? this.EanbleCabinetInsideSmallDimSize / 2 : 1));
// TestDraw(pl);
// for (let oo of opls)
// TestDraw(oo, 1);
if (opls.length !== 1 || opls[0].EndParam !== pl.EndParam) continue;
// let size = opls[0].BoundingBoxInOCS.getSize(new Vector3);
for (let cu of pl.Explode())
{
if (cu instanceof Arc) continue;
let derv = cu.GetFistDeriv(0).normalize();
if (equaln(derv.x, 1))//down
{
if (!this.EnableCabinetInsideWidth) continue;
// if (size.y < 300) continue;
let [p1, p2] = [cu.StartPoint, cu.EndPoint];
let key = `${p1.x.toFixed(3)},${p2.x.toFixed(3)}`;
if ([alldimkeys[0], alldimkeys[1]].some(dims => dims.has(key)))
continue;
let a1 = p1.clone();
let a2 = p2.clone();
a1.y += 50;
a2.y += 50;
let alDim = new AlignedDimension(p1, p2, a1, a2);
alDim.ApplyMatrix(spaceFrontCS);
Draw(alDim);
alldimkeys[0].add(key);
}
else if (equaln(derv.x, -1))//top
{
if (!this.EnableCabinetInsideWidth) continue;
// if (size.y < 300) continue;
let [p1, p2] = [cu.StartPoint, cu.EndPoint];
let key = `${p2.x.toFixed(3)},${p1.x.toFixed(3)}`;
if ([alldimkeys[0], alldimkeys[1]].some(dims => dims.has(key)))
continue;
let a1 = p1.clone();
let a2 = p2.clone();
a1.y -= 50;
a2.y -= 50;
let alDim = new AlignedDimension(p1, p2, a1, a2);
alDim.ApplyMatrix(spaceFrontCS);
Draw(alDim);
alldimkeys[1].add(key);
}
else if (equaln(derv.y, 1))//right
{
if (!this.EnableCabinetInsideHeight) continue;
//if (size.x < 300) continue;
let [p1, p2] = [cu.StartPoint, cu.EndPoint];
let key = `${p1.y.toFixed(3)},${p2.y.toFixed(3)}`;
if ([alldimkeys[2], alldimkeys[3]].some(dims => dims.has(key)))
continue;
let a1 = p1.clone();
let a2 = p2.clone();
a1.x -= 50;
a2.x -= 50;
let alDim = new AlignedDimension(p1, p2, a1, a2);
alDim.ApplyMatrix(spaceFrontCS);
Draw(alDim);
alldimkeys[3].add(key);
}
else if (equaln(derv.y, -1))//left
{
if (!this.EnableCabinetInsideHeight) continue;
//if (size.x < 300) continue;
let [p1, p2] = [cu.StartPoint, cu.EndPoint];
let key = `${p2.y.toFixed(3)},${p1.y.toFixed(3)}`;
if ([alldimkeys[2], alldimkeys[3]].some(dims => dims.has(key)))
continue;
let a1 = p1.clone();
let a2 = p2.clone();
a1.x += 50;
a2.x += 50;
let alDim = new AlignedDimension(p1, p2, a1, a2);
alDim.ApplyMatrix(spaceFrontCS);
Draw(alDim);
alldimkeys[3].add(key);
}
}
}
//#endregion 内空标注
}
//没有允许整体标注
if (!this.EnableDimAllSize) continue;
//#region 整体标注
//前视图 top 1 right 3
//top
{
let maxLead = 0;
for (let al of alldims[1])
if (al.LeadVisible && al.NeedLead)
maxLead = Math.max(maxLead, al.LeadY);
let f1 = new Vector3(groupSpaceBox.min.x, groupSpaceBox.max.z, 0);
let f2 = f1.clone().setX(groupSpaceBox.max.x);
let a1 = f1.clone();
let a2 = f2.clone();
let moveY = maxLead;
if (alldims[1].length) moveY += 90;
a1.y += offsetYDist + moveY;
a2.y += offsetYDist + moveY;
let topAl = new AlignedDimension(f1, f2, a1, a2);
topAl.ApplyMatrix(spaceFrontCS);
Draw(topAl);
}
//right
{
let maxLead = 0;
for (let al of alldims[3])
if (al.LeadVisible && al.NeedLead)
maxLead = Math.max(maxLead, al.LeadY);
let f1 = new Vector3(groupSpaceBox.max.x, groupSpaceBox.min.z, 0);
let f2 = f1.clone().setY(groupSpaceBox.max.z);
let a1 = f1.clone();
let a2 = f2.clone();
let moveY = maxLead;
if (alldims[3].length) moveY += 90;
a1.x += offsetYDist + moveY;
a2.x += offsetYDist + moveY;
let rightAl = new AlignedDimension(f1, f2, a1, a2);
rightAl.ApplyMatrix(spaceFrontCS);
Draw(rightAl);
}
let fsCS = spaceCS.clone();
if (!equaln(groupSpaceBox.min.z, 0))
{
fsCS.elements[12] += z.x * groupSpaceBox.min.z;
fsCS.elements[13] += z.y * groupSpaceBox.min.z;
fsCS.elements[14] += z.z * groupSpaceBox.min.z;
}
//俯视图前面
{
let f1 = new Vector3(groupSpaceBox.min.x, groupSpaceBox.max.y, 0);
let f2 = f1.clone().setX(groupSpaceBox.max.x);
let a1 = f1.clone();
let a2 = f2.clone();
a1.y += offsetYDist;
a2.y += offsetYDist;
let fs_front = new AlignedDimension(f1, f2, a1, a2);
fs_front.ApplyMatrix(fsCS);
Draw(fs_front);
}
//俯视图右
{
let f1 = new Vector3(groupSpaceBox.max.x, groupSpaceBox.min.y, 0);
let f2 = f1.clone().setY(groupSpaceBox.max.y);
let a1 = f1.clone();
let a2 = f2.clone();
a1.x += offsetYDist;
a2.x += offsetYDist;
let fs_right = new AlignedDimension(f1, f2, a1, a2);
fs_right.ApplyMatrix(fsCS);
Draw(fs_right);
}
//#endregion
}
}
/**
*
* @param foots
* @param als
* @param j down top left right 0 1 2 3
*/
static DimAvoid(foots: number[], als: AlignedDimension[], j: number)
{
//down top left right 0 1 2 3
let filpLeads = [true, false, false, true];
let midX = (arrayLast(foots) + foots[0]) * 0.5;
for (let k = 0; k < als.length; k++)
{
let al = als[k];
if (!al.Visible || !al.NeedLead)//被过滤的实体不需要避让
continue;
let nextDim = als[k + 1];
let nowDist = al.Distance;
if (k === 0) //最左边的那个
{
if (!nextDim || ((nextDim.Distance + nowDist) * 0.5) > ((al.TextBoxWidth + nextDim.TextBoxWidth) * 0.5))
al.LeadVisible = false; //可以被放下 且不和别人冲突
else
al.SetLeadData(new Vector2(-30, 30), filpLeads[j]);
continue;
}
let preDim = als[k - 1];
let preDist = preDim.Distance;
if (equaln(preDist, nowDist)) //合并引线(我们总是考虑下一个标注,所以我们可以放心的合并引线)
{
let p = new Vector3(preDim.LeadX, preDim.LeadY, 0);
p.applyMatrix4(preDim.DalUcs); //对象坐标系内
let dalUcs = al.DalUcs; //不可用了
let dalUcsInv = dalUcs.getInverse(dalUcs);
p.applyMatrix4(dalUcsInv);
al.SetLeadData(AsVector2(p));
continue;
}
if (k === als.length - 1) //如果是最后一个
{
if (((preDist + nowDist) * 0.5) > ((al.TextBoxWidth + preDim.TextBoxWidth) * 0.5))
al.LeadVisible = false; //可以被放下 且不和别人冲突
else
al.SetLeadData(new Vector2(30, 30), filpLeads[j]);
continue;
}
let nextDist = nextDim.Distance;
if (!preDim.NeedLead && !nextDim.NeedLead
&& (((preDist + nowDist) * 0.5) > ((al.TextBoxWidth + preDim.TextBoxWidth) * 0.5))
&& (((nextDist + nowDist) * 0.5) > ((al.TextBoxWidth + nextDim.TextBoxWidth) * 0.5)))
{
al.LeadVisible = false; //可以被放下 且不和别人冲突
continue;
}
//#region 因为可放标注不在提供引线后,下面这个查表的代码似乎没有意义了.(左侧优先或者右侧优先? 没意义了 如果两侧都可以放的下的时候 不在需要这个优先了 因为不在飞了)
//现在开始,我们是第一个(前面必然不需要引线,需要为后续所有需要连续的引线负责)
let xIndex = Math.floor(j / 2);//x y 0 1
let x = midPoint(al.ArmP1, al.ArmP2).applyMatrix4(al.OCSInv).getComponent(xIndex); //中心点
//查表
let list = [
[[preDim, nextDim], [preDist, nextDist], [-30, 30]],
[[nextDim, preDim], [nextDist, preDist], [30, -30]]
];
if (x > midX)
list.reverse(); //右侧优先
if (list.some(lst =>
{
return [0, 1].some(i =>
{
let otherDim = lst[0][i] as AlignedDimension;
let otherDist = lst[1][i] as number;
if (otherDist > 500 && !otherDim.NeedLead)
{
if (((otherDist + nowDist) * 0.5 - 40) < ((al.TextBoxWidth + otherDim.TextBoxWidth) * 0.5))
al.SetLeadData(new Vector2(lst[2][i] as number, 80), filpLeads[j]);
else
al.SetLeadData(new Vector2(lst[2][i] as number, 40), filpLeads[j]);
return true;
}
});
}))
continue;
//#endregion
//能左移的已经左移,能右移的已经右移,现在我们要对多个堆进行出手了!
let dims = [al];
for (let l = k + 1; l < als.length; l++)
{
let dim = als[l];
if (!dim.NeedLead)
break;
dims.push(dim);
}
//删除重复的标注
let dims2 = arrayRemoveDuplicateBySort(dims.concat(), (d1, d2) => d1.TextString === d2.TextString);
let midIndex = Math.floor(dims2.length / 2);
if (!preDim.NeedLead && preDist < 450)
midIndex = 0;
const yMove = 90;
//左侧
let p = new Vector3(-30, 110, 0);
if (preDim.NeedLead)
p.y = preDim.LeadY + yMove;
if (filpLeads[j])
p.x *= -1;
p.applyMatrix4(dims[0].DalUcs); //对象坐标系内
for (let l = 0; l < midIndex; l++)
{
let dim = dims2[l];
if (!dim.Visible) continue;//被过滤的实体不影响避让
let dalUCS = dim.DalUcs;
let dalUcsInv = dalUCS.clone().getInverse(dalUCS);
let leadP = p.applyMatrix4(dalUcsInv);
dim.SetLeadData(AsVector2(leadP));
p.y += yMove;
p.applyMatrix4(dalUCS);
}
//右侧
p = new Vector3(30, 110, 0);
if (dims[dims.length - 1] === als[als.length - 1])
p.y = 30;
if (filpLeads[j])
p.x *= -1;
p.applyMatrix4(dims[dims.length - 1].DalUcs); //对象坐标系内
for (let l = dims2.length; l--, l >= midIndex;)
{
let dim = dims2[l];
if (!dim.Visible) continue;//被过滤的实体不影响避让
let dalUCS = dim.DalUcs;
let dalUcsInv = dalUCS.clone().getInverse(dalUCS);
let leadP = p.applyMatrix4(dalUcsInv);
dim.SetLeadData(AsVector2(leadP));
p.y += yMove;
p.applyMatrix4(dalUCS);
}
//合并同尺寸标注
arrayRemoveDuplicateBySort(dims, (d1, d2) =>
{
if (d1.TextString === d2.TextString)
{
let p = new Vector3(d1.LeadX, d1.LeadY, 0);
p.applyMatrix4(d1.DalUcs); //对象坐标系内
let dalUcs = d2.DalUcs; //不可用了
let dalUcsInv = dalUcs.getInverse(dalUcs);
p.applyMatrix4(dalUcsInv);
d2.SetLeadData(AsVector2(p));
}
return false;
});
k += dims.length;
}
}
}
//过滤斜层板和被旋转的板
export function FilterDimBoardFn(br: Board): boolean
{
//非正常旋转
if (!equaln(MathUtils.radToDeg(br.Rotation.x) % 90, 0)
|| !equaln(MathUtils.radToDeg(br.Rotation.y) % 90, 0)
|| !equaln(MathUtils.radToDeg(br.Rotation.z) % 90, 0))
return false;
let normal = br.Normal;
//过滤掉斜层板?
if (!(isParallelTo(ZAxis, normal) || isPerpendicularityTo(ZAxis, normal)))
return false;
return true;
}

@ -1,33 +1,44 @@
import { Vector3 } from "three";
import { app } from "../../ApplicationServices/Application";
import { UpdateDraw } from "../../Common/Status";
import { JigUtils } from "../../Editor/JigUtils";
import { PromptStatus } from "../../Editor/PromptResult";
import { Dimension } from "./Command_DimContinue";
import { UpdateDraw } from "../../Common/Status";
export class DimContinue
export abstract class DimContinue
{
protected m_LastDim: Dimension;
protected m_BasePoint: Vector3;
protected _LastDim: Dimension;
protected _BasePoint: Vector3;
//开始绘制.
async StartDraw(lastDim: Dimension)
{
this.m_LastDim = lastDim.Clone();
this._LastDim = lastDim.Clone();
let oldUcs = app.Editor.UCSMatrix;
app.Editor.UCSMatrix = this.m_LastDim.OCS;
app.Editor.UCSMatrix = this._LastDim.OCS;
while (true)
{
let newDim = this.CloneDimension(this.m_LastDim);
let newDim = this.CloneDimension(this._LastDim);
JigUtils.Draw(newDim);
let ptRes = await app.Editor.GetPoint({
AllowNone: true,
BasePoint: this.m_BasePoint,
BasePoint: this._BasePoint,
Msg: "指定第二个尺寸原点",
Callback: p => this.UpdateNextPoint(p, newDim)
Callback: p =>
{
if (this.UpdateNextPoint(p, newDim))
newDim.Visible = false;
else
newDim.Visible = true;
}
});
if (ptRes.Status === PromptStatus.OK)
{
let p = ptRes.Point;
this.UpdateNextPoint(p, newDim);
if (this.UpdateNextPoint(p, newDim))
{
JigUtils.End();
continue;//点不被接受
}
newDim.Visible = true;
app.Database.ModelSpace.Append(newDim);
if (!app.Viewer.UsePass)
newDim.Text.Update(UpdateDraw.Geometry);
@ -44,30 +55,25 @@ export class DimContinue
* @param dim
* @returns and jig draw
*/
protected CloneDimension(dim: Dimension): Dimension
{
return undefined;
}
protected abstract CloneDimension(dim: Dimension): Dimension;
/**
* :,
* @param p
* @param dim
*/
protected UpdateNextPoint(p: Vector3, dim: Dimension)
{
}
protected abstract UpdateNextPoint(p: Vector3, dim: Dimension);
/**
* ,
* @param dim
*/
protected Drawed(dim: Dimension, p: Vector3)
{
}
protected abstract Drawed(dim: Dimension, p: Vector3);
/**
* :,
*/
protected EndDraw()
{
this.m_LastDim.GoodBye();
this._LastDim.GoodBye();
}
}

@ -5,7 +5,7 @@ import { DimContinue } from "./DimContinue";
//对齐标注的连续标注
export class DimContinueAligen extends DimContinue
{
private m_line: Line;
private _line: Line;
/**
* : ,,
* @param dim
@ -16,9 +16,9 @@ export class DimContinueAligen extends DimContinue
let ndim = dim.Clone();
ndim.FootP1 = dim.FootP2;
ndim.ArmP1 = dim.ArmP2;
this.m_BasePoint = dim.FootP2;
if (!this.m_line)
this.m_line = new Line(dim.ArmP1, dim.ArmP2);
this._BasePoint = dim.FootP2;
if (!this._line)
this._line = new Line(dim.ArmP1, dim.ArmP2);
return ndim;
}
/**
@ -28,8 +28,8 @@ export class DimContinueAligen extends DimContinue
*/
protected UpdateNextPoint(p: Vector3, dim: AlignedDimension)
{
let last = this.m_LastDim as AlignedDimension;
let { closestPt, param } = this.m_line.GetClosestAtPoint(p, true);
let last = this._LastDim as AlignedDimension;
let { closestPt, param } = this._line.GetClosestAtPoint(p, true);
if (param > 1)
{
dim.FootP1 = last.FootP2;
@ -51,8 +51,8 @@ export class DimContinueAligen extends DimContinue
*/
protected Drawed(dim: AlignedDimension, p: Vector3)
{
let last = this.m_LastDim as AlignedDimension;
let { param } = this.m_line.GetClosestAtPoint(p, true);
let last = this._LastDim as AlignedDimension;
let { param } = this._line.GetClosestAtPoint(p, true);
if (param > 1)
{
last.FootP2 = p;
@ -63,7 +63,7 @@ export class DimContinueAligen extends DimContinue
last.FootP1 = p;
last.ArmP1 = dim.ArmP1;
}
this.m_line.Join(new Line(dim.ArmP1, dim.ArmP2));
this._line.Join(new Line(dim.ArmP1, dim.ArmP2));
}
/**
* :,
@ -71,7 +71,7 @@ export class DimContinueAligen extends DimContinue
protected EndDraw()
{
super.EndDraw();
this.m_line.GoodBye();
this.m_line = undefined;
this._line.GoodBye();
this._line = undefined;
}
}

@ -1,8 +1,8 @@
import { Vector3 } from "three";
import { Arc } from "../../DatabaseServices/Entity/Arc";
import { LineAngularDimension } from "../../DatabaseServices/Dimension/2LineAngularDimension";
import { Arc } from "../../DatabaseServices/Entity/Arc";
import { Line } from "../../DatabaseServices/Entity/Line";
import { equalv3 } from "../../Geometry/GeUtils";
import { equaln, equalv3 } from "../../Geometry/GeUtils";
import { DimContinue } from "./DimContinue";
//2直线角度标注的连续标注
export class DimContinueLineAngular extends DimContinue
@ -32,8 +32,8 @@ export class DimContinueLineAngular extends DimContinue
*/
protected Drawed(dim: LineAngularDimension, p: Vector3)
{
this.m_LastDim.GoodBye();
this.m_LastDim = dim.Clone();
this._LastDim.GoodBye();
this._LastDim = dim.Clone();
}
/**
* :,
@ -45,6 +45,8 @@ export class DimContinueLineAngular extends DimContinue
let cp = this._arc.GetClosestPointTo(p, true);
let newL1Ep: Vector3;
let param = this._arc.GetParamAtPoint(cp);
if (equaln(param, 0) || equaln(param, 1) || equalv3(p, this._arc.Center)) return true;
let arcSpOnL1 = !isNaN(new Line(this._l1Sp, this._l1Ep).GetParamAtPoint(this._arc.StartPoint));
if (param > 0.5)
{
@ -56,8 +58,6 @@ export class DimContinueLineAngular extends DimContinue
this._narc.StartAngle = this._arc.GetAngleAtParam(1);
this._narc.EndAngle = this._arc.GetAngleAtParam(param);
}
else if (param === 1)
return;
else
{
this._narc.StartAngle = this._arc.GetAngleAtParam(param);
@ -80,8 +80,7 @@ export class DimContinueLineAngular extends DimContinue
this._narc.EndAngle = this._arc.GetAngleAtParam(param);
}
}
if (equalv3(p, this._arc.Center))
return;
dim.UpdateDimData(this._arc.Center, newL1Ep, this._arc.Center, p, this._narc.GetPointAtParam(0.5));
}
/**

@ -3,6 +3,7 @@ import { app } from "../../ApplicationServices/Application";
import { UpdateDraw } from "../../Common/Status";
import { LineAngularDimension } from "../../DatabaseServices/Dimension/2LineAngularDimension";
import { Arc } from "../../DatabaseServices/Entity/Arc";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Circle } from "../../DatabaseServices/Entity/Circle";
import { Curve } from "../../DatabaseServices/Entity/Curve";
import { Line } from "../../DatabaseServices/Entity/Line";
@ -10,7 +11,6 @@ import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { JigUtils } from "../../Editor/JigUtils";
import { PromptStatus } from "../../Editor/PromptResult";
import { isParallelTo } from "../../Geometry/GeUtils";
import { Board } from "../../ueapi";
import { ContinueDrawDimension } from "./Command_DimContinue";
export class Command_Draw2LineAngularDim

@ -1,4 +1,4 @@
import { Matrix4, Vector3 } from 'three';
import { Vector3 } from 'three';
import { app } from '../../ApplicationServices/Application';
import { AlignedDimension } from '../../DatabaseServices/Dimension/AlignedDimension';
import { LinearDimension } from '../../DatabaseServices/Dimension/LinearDimension';
@ -20,20 +20,38 @@ export enum DimensionType
Linear = 1 //线性标注
}
//dli
export class DrawAlignedDimension implements Command
{
protected DimType = DimensionType.Align;
protected _UseFirstPointUCS = true;
async exec()
{
let ptRes = await app.Editor.GetPoint({ Msg: "请指定第一条尺寸线原点:", AllowNone: true });
while (true)
{
let ptRes = await app.Editor.GetPoint({
Msg: "请指定第一条尺寸线原点:",
AllowNone: true,
KeyWordList: [
{ msg: this._UseFirstPointUCS ? "使用UCS坐标系标注" : "使用第一点所在平面标注", key: "S" }
]
});
if (ptRes.Status === PromptStatus.String)
{
this._UseFirstPointUCS = !this._UseFirstPointUCS;
continue;
}
if (ptRes.Status === PromptStatus.OK)
await this.SelectPointDim(ptRes.Point);
await this.GetPointDli(ptRes.Point);
if (ptRes.Status === PromptStatus.None)
await this.PickUpDim();
await this.GetEntityDli();
break;
}
protected async SelectPointDim(footPt1: Vector3)
}
protected async GetPointDli(footPt1: Vector3)
{
let ptRes = await app.Editor.GetPoint({
Msg: "请输入第二条尺寸线原点:",
@ -44,14 +62,11 @@ export class DrawAlignedDimension implements Command
return;
let footPt2 = ptRes.Point;
let ucs = app.Editor.UCSMatrix.clone().setPosition(footPt1);
let ucsInv = new Matrix4().getInverse(ucs);
footPt2.applyMatrix4(ucsInv).setZ(0).applyMatrix4(ucs);
await this.BuildDim(footPt1, footPt2);
}
//选择对象标注
private async PickUpDim()
private async GetEntityDli()
{
let enRes = await app.Editor.GetEntity({
Msg: "选择对象",
@ -104,7 +119,10 @@ export class DrawAlignedDimension implements Command
else
alDim = new LinearDimension();
alDim.ApplyMatrix(app.Editor.UCSMatrix);
let ocs = app.Editor.UCSMatrix;
if (this._UseFirstPointUCS)
ocs.setPosition(footPt1);
alDim.ApplyMatrix(ocs);
alDim.FootP1 = footPt1;
alDim.ArmP1 = footPt1;
@ -121,9 +139,6 @@ export class DrawAlignedDimension implements Command
if (ptRes.Status == PromptStatus.OK)
{
alDim.TextPosition = ptRes.Point;
//抬高footers
alDim.RaiseFooters(FootersRaiseValue);
app.Database.ModelSpace.Append(alDim);
await ContinueDrawDimension(alDim);
}

@ -1,13 +1,14 @@
import { Box3, MathUtils, Matrix4, Vector3 } from "three";
import { Box3, Vector3 } from "three";
import { app } from "../../ApplicationServices/Application";
import { arrayRemoveDuplicateBySort, arraySortByNumber } from "../../Common/ArrayExt";
import { Draw } from "../../Common/Draw";
import { AlignedDimension } from "../../DatabaseServices/Dimension/AlignedDimension";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Command } from "../../Editor/CommandMachine";
import { JigUtils } from "../../Editor/JigUtils";
import { PromptStatus } from "../../Editor/PromptResult";
import { CoordinateSystem } from "../../Geometry/CoordinateSystem";
import { equaln } from "../../Geometry/GeUtils";
import { Command_AutoDimBrs } from "./AutoDimBrs";
import { PromptSsgetResult, PromptStatus } from "../../Editor/PromptResult";
import { equalnn } from "../../Geometry/GeUtils";
import { DimBoards, FilterDimBoardFn } from "./DimBoards";
enum Direction
{
@ -18,28 +19,32 @@ enum Direction
top = 8
}
const DEG90 = 90;//90°
export class Command_FastDimBrs implements Command
{
async exec()
{
//选择板件
let enRes = await app.Editor.GetSelection({
let enRes: PromptSsgetResult;
let dimAll = false;
while (true)
{
enRes = await app.Editor.GetSelection({
UseSelect: true,
Msg: "选择需要标注的板件",
KeyWordList: [{ msg: dimAll ? "关闭整体标注" : "整体标注", key: "S" }],
Filter: { filterTypes: [Board] },
});
if (enRes.Status === PromptStatus.Keyword)
dimAll = !dimAll;
else
break;
}
if (enRes.Status === PromptStatus.Cancel) return;
let brs = enRes.SelectSet.SelectEntityList as Board[];
//排除旋转角度非90度倍数的板件
brs = brs.filter(b => (
equaln(MathUtils.radToDeg(b.Rotation.x) % (DEG90), 0)
&& equaln(MathUtils.radToDeg(b.Rotation.y) % (DEG90), 0)
&& equaln(MathUtils.radToDeg(b.Rotation.z) % (DEG90), 0)
));
brs = brs.filter(FilterDimBoardFn);
if (brs.length === 0)
{
@ -49,45 +54,23 @@ export class Command_FastDimBrs implements Command
app.Editor.Prompt(`可标注板件数: ${brs.length}`);
let autoDim = new Command_AutoDimBrs();
let tool = new FastDimTool(brs);
tool.enableDimAll = dimAll;
let ucs = app.Editor.UCSMatrix;
let ucsInv = app.Editor.UCSMatrixInv;
let ucsDir = new Vector3().setFromMatrixColumn(app.Editor.UCSMatrix, 2);
let isFS = ucsDir.equals(new Vector3(-0, -0, 1));
let oldState = Direction.left;
let brBoxs = brs.map(br =>
const CreateDims = (p: Vector3) =>
{
return br.BoundingBoxInOCS.applyMatrix4(ucsInv.clone().multiply(br.OCS));
});
let boxAll = new Box3();
for (let box of brBoxs)
boxAll.union(box);
let cs = new CoordinateSystem().CopyForm(ucs);
let pUcs = p.clone().applyMatrix4(tool.ucsInv);
let state = 0;
let state = Direction.None;
let als: AlignedDimension[] = [];
let ptRes = await app.Editor.GetPoint({
Msg: "指定尺寸线位置:",
Callback: p =>
{
let pUcs = p.clone().applyMatrix4(ucsInv);
let drawCS = new Matrix4();
let textRo = 0;
let oldState = state;
state = 0;
if (pUcs.x > boxAll.max.x)
if (pUcs.x > tool.allBox.max.x)
state |= Direction.right;
if (pUcs.y > boxAll.max.y)
if (pUcs.y > tool.allBox.max.y)
state |= Direction.top;
if (pUcs.y < boxAll.min.y)
if (pUcs.y < tool.allBox.min.y)
state |= Direction.down;
if (pUcs.x < boxAll.min.x)
if (pUcs.x < tool.allBox.min.x)
state |= Direction.left;
if (oldState & state)
@ -95,45 +78,141 @@ export class Command_FastDimBrs implements Command
else if (state === 0)
state = oldState;
if (state & Direction.left)
JigUtils.Destroy();
let als: AlignedDimension[] = [];
for (let dir of [Direction.down, Direction.top, Direction.left, Direction.right])
if (dir & state)
{
textRo = Math.PI;
drawCS.makeBasis(cs.YAxis.clone().negate(), cs.XAxis, cs.ZAxis);
als = tool.CreateDims(dir, pUcs);
oldState = dir;
break;
}
else if (state & Direction.right)
return als;
};
while (true)
{
textRo = Math.PI;
drawCS.makeBasis(cs.YAxis, cs.XAxis.clone().negate(), cs.ZAxis);
}
else if (state & Direction.down)
let ptRes = await app.Editor.GetPoint({
Msg: "指定尺寸线位置:",
KeyWordList: [{ msg: tool.enableDimAll ? "关闭整体标注" : "整体标注", key: "S" }],
Callback: p =>
{
textRo = 0;
drawCS.copy(ucs);
let als = CreateDims(p);
for (let al of als)
JigUtils.Draw(al);
}
else if (state & Direction.top)
});
if (ptRes.Status === PromptStatus.Keyword)
tool.enableDimAll = !tool.enableDimAll;
else
{
if (ptRes.Status === PromptStatus.OK)
{
textRo = Math.PI;
drawCS.makeBasis(cs.XAxis.clone().negate(), cs.YAxis.clone().negate(), cs.ZAxis);
let als = CreateDims(ptRes.Point);
for (let al of als)
Draw(al);
}
return;
}
}
JigUtils.Destroy();
}
}
export class FastDimTool
{
//这个UCS会比适当的修改,保证绘图平面和选择的板在一个平面内
ucs = app.Editor.UCSMatrix;
ucsInv = app.Editor.UCSMatrixInv;
allBox = new Box3;
footss: [number[], number[]] = [[], []];
enableDimAll = true;//全长标注
constructor(
public brs: Board[]
)
{
//x,y
for (let br of brs)
{
let box = br.GetBoundingBoxInMtx(this.ucsInv);
als = autoDim.DrawDim(brs, drawCS, textRo, true, !isFS);
for (let i = 0; i < 2; i++)
this.footss[i].push(box.min.getComponent(i), box.max.getComponent(i));
for (let aldim of als)
this.allBox.union(box);
}
//绘图平面对齐
let z = new Vector3().setFromMatrixColumn(this.ucs, 2);
this.ucs.elements[12] += z.x * this.allBox.max.z;
this.ucs.elements[13] += z.y * this.allBox.max.z;
this.ucs.elements[14] += z.z * this.allBox.max.z;
//排序和去重
for (let i = 0; i < 2; i++)
{
aldim.TextPosition = p;
arraySortByNumber(this.footss[i]);
arrayRemoveDuplicateBySort(this.footss[i], equalnn(3));
}
}
});
if (ptRes.Status === PromptStatus.OK)
CreateDims(dir: Direction, pUcs: Vector3)
{
for (let aldim of als)
//左右上下0 1 2 3
let index = [Direction.down, Direction.top, Direction.left, Direction.right].indexOf(dir);
let xIndex = Math.floor(index / 2);
let yIndex = Math.abs(1 - xIndex);
let armY = pUcs.getComponent(yIndex);
let sign = Math.sign(index % 2 - 0.5);
let footY = armY - (sign * 130);//y offset(move) dist = 130
let foots = this.footss[xIndex];
let als: AlignedDimension[] = [];
for (let i = 0; i < foots.length - 1; i++)
{
aldim.TextPosition = ptRes.Point;
app.Database.ModelSpace.Append(aldim);
let x1 = foots[i];//假设是x 其实可能是y
let x2 = foots[i + 1];
let f1 = new Vector3().setComponent(xIndex, x1).setComponent(yIndex, footY);
let f2 = new Vector3().setComponent(xIndex, x2).setComponent(yIndex, footY);
let a1 = f1.clone().setComponent(yIndex, armY);
let a2 = f2.clone().setComponent(yIndex, armY);
let alDim = new AlignedDimension(f1, f2, a1, a2);
alDim.ApplyMatrix(this.ucs);
als.push(alDim);
}
DimBoards.DimAvoid(foots, als, index);//标注避让
//标注全长
if (this.enableDimAll && foots.length > 2)
{
let maxLead = 0;
for (let al of als)
if (al.LeadVisible && al.NeedLead)
maxLead = Math.max(maxLead, al.LeadY);
let moveY = (maxLead + 90) * sign;
let f1 = new Vector3().setComponent(xIndex, foots[0]).setComponent(yIndex, footY + moveY);
let f2 = new Vector3().setComponent(xIndex, foots[foots.length - 1]).setComponent(yIndex, footY + moveY);
let a1 = f1.clone().setComponent(yIndex, armY + moveY);
let a2 = f2.clone().setComponent(yIndex, armY + moveY);
let alDim = new AlignedDimension(f1, f2, a1, a2);
alDim.ApplyMatrix(this.ucs);
als.push(alDim);
}
return als;
}
}

@ -3,7 +3,6 @@ import * as React from 'react';
import { MathUtils, Vector3 } from 'three';
import { OBJExporter } from 'three/examples/jsm/exporters/OBJExporter';
import { begin } from 'xaop';
import { CADFiler } from '../api';
import { app } from "../ApplicationServices/Application";
import { IsDev } from '../Common/Deving';
import { CURRENT_HOST, RenderUrl } from "../Common/HostUrl";
@ -17,6 +16,7 @@ import { CylinderHole } from '../DatabaseServices/3DSolid/CylinderHole';
import { ExtrudeHole } from '../DatabaseServices/3DSolid/ExtrudeHole';
import { RevolveSolid } from '../DatabaseServices/3DSolid/RevolveSolid';
import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid";
import { CADFiler } from '../DatabaseServices/CADFiler';
import { Arc } from '../DatabaseServices/Entity/Arc';
import { Board } from "../DatabaseServices/Entity/Board";
import { Circle } from "../DatabaseServices/Entity/Circle";
@ -39,6 +39,7 @@ import { PhysicalMaterialRecord } from "../DatabaseServices/PhysicalMaterialReco
import { RoomFlatBase } from '../DatabaseServices/Room/Entity/Flat/RoomFlatBase';
import { RoomHolePolyline } from '../DatabaseServices/Room/Entity/Wall/Hole/RoomHolePolyline';
import { CURVE_FACE_TYPE_KEY, RoomWallBase } from '../DatabaseServices/Room/Entity/Wall/RoomWallBase';
import { RoomWallParse } from '../DatabaseServices/Room/ParseService/RoomWallParse';
import { Shape } from "../DatabaseServices/Shape";
import { TextureTableRecord } from "../DatabaseServices/Texture";
import { Command } from "../Editor/CommandMachine";
@ -47,7 +48,6 @@ import { IdentityMtx4 } from '../Geometry/GeUtils';
import { Orbit } from '../Geometry/Orbit';
import { RenderType } from '../GraphicsSystem/RenderType';
import { arrayPushArray } from '../Nest/Common/ArrayExt';
import { RoomWallParse } from '../ueapi';
import { GetCompoentObjectIdString } from '../UI/Components/ComponentObjectId';
import { ModalFooter, ModalHeader } from '../UI/Components/Modal/ModalContainer';
import { ModalPosition } from '../UI/Components/Modal/ModalInterface';

@ -1,8 +1,8 @@
import { app } from "../../ApplicationServices/Application";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { Polyline } from "../../ueapi";
export class Command_Fix2DPath implements Command
{

@ -1,9 +1,9 @@
import { EBoardKeyList } from "../../../Common/BoardKeyList";
import { IsMeshMaterialEntity } from "../../../Common/IsMeshMaterialEntity";
import { Board } from "../../../DatabaseServices/Entity/Board";
import { Entity } from "../../../DatabaseServices/Entity/Entity";
import { HardwareCompositeEntity } from "../../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { PhysicalMaterialRecord } from "../../../DatabaseServices/PhysicalMaterialRecord";
import { Board } from "../../../ueapi";
import { ApplyGoodInfo } from "../../../UI/Components/ApplyGoodInfo";
import { KJL_Parameter, KJL_ParamModel_Hardware } from "./KJLInterface";

@ -1,7 +1,8 @@
import { Arc, Polyline } from "../../api";
import { app } from "../../ApplicationServices/Application";
import { Draw } from "../../Common/Draw";
import { Arc } from "../../DatabaseServices/Entity/Arc";
import { Line } from "../../DatabaseServices/Entity/Line";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { RoomWallArc } from "../../DatabaseServices/Room/Entity/Wall/RoomWallArc";
import { RoomWallLine } from "../../DatabaseServices/Room/Entity/Wall/RoomWallLine";
import { Command } from "../../Editor/CommandMachine";

@ -1,9 +1,9 @@
import { Intent } from "@blueprintjs/core";
import { CADFiler } from "../api";
import { app } from "../ApplicationServices/Application";
import { deflate } from "../Common/SerializeMaterial";
import { DuplicateRecordCloning } from "../Common/Status";
import { copyTextToClipboard } from "../Common/Utils";
import { CADFiler } from "../DatabaseServices/CADFiler";
import { Database } from "../DatabaseServices/Database";
import { Entity } from "../DatabaseServices/Entity/Entity";
import { IdMaping } from "../DatabaseServices/IdMaping";

@ -1,10 +1,10 @@
import { Vector3 } from "three";
import { Polyline } from "../api";
import { app } from "../ApplicationServices/Application";
import { Intent } from "../Common/Toaster";
import { FixedNotZero } from "../Common/Utils";
import { Board } from "../DatabaseServices/Entity/Board";
import { Curve } from "../DatabaseServices/Entity/Curve";
import { Polyline } from "../DatabaseServices/Entity/Polyline";
import { Text, TextAligen } from "../DatabaseServices/Text/Text";
import { Command } from "../Editor/CommandMachine";
import { PromptStatus } from "../Editor/PromptResult";

@ -7,6 +7,5 @@ export class Test implements Command
{
async exec()
{
}
}

@ -1,5 +1,6 @@
import { MeshBasicMaterial, MeshStandardMaterial, Texture } from 'three';
import { FractionDigitsType } from '../Common/SystemEnum';
import { ObjectId } from '../DatabaseServices/ObjectId';
import { ICursorConfig } from '../Editor/ICursorConfig';
import { RenderType } from '../GraphicsSystem/RenderType';
import { DrillingOption } from '../UI/Store/drillInterface';
@ -7,6 +8,7 @@ import { DrillingOption } from '../UI/Store/drillInterface';
export class IHostApplicationServices
{
DefaultMeshMaterial?: MeshBasicMaterial | MeshStandardMaterial;
CurrentDimStyle: ObjectId;
@ProxyValue isShowLightShadow: boolean = true;//灯光阴影 (除太阳光外)
ShowHistoryLog: boolean = true;

@ -117,7 +117,7 @@ export enum CommandNames
AddPtOnBoard = "ADDPTONBOARD",
DeletePtOnBoard = "DELETEPTONBOARD",
BoardFindModify = "BOARDFINDMODIFY",
LookOverBoardInfos = "LOOKOVERBOARDINFOS",
LookOverBoardInfos = "LOOKOVERBOARDINFOS",//BBS
BoardBatchCurtail = "BOARDBATCHCURTAIL",
AutoDimBrs = "AUTODIMBRS",
FastDimBrs = "FASTDIMBRS",

@ -1,5 +1,5 @@
import { SymbolTable } from "./SymbolTable";
import { Factory } from "./CADFactory";
import { SymbolTable } from "./SymbolTable";
@Factory
export class BlockTable extends SymbolTable

@ -3,6 +3,7 @@ import { Status } from '../Common/Status';
import { Factory } from './CADFactory';
import { CADFiler } from './CADFiler';
import { Database } from './Database';
import { Dimension } from './Dimension/Dimension';
import { Entity } from './Entity/Entity';
import { ObjectCollection } from './ObjectCollection';
import { SymbolTableRecord } from './SymbolTableRecord';
@ -24,10 +25,9 @@ export class BlockTableRecord extends SymbolTableRecord
return this;
}
get Entitys()
{
return this.EntityCol.Objects;
}
get Entitys() { return this.EntityCol.Objects; }
/** 提供通用的Add方法(以便在WblockClone时能统一调用.Add) */
Add(obj: Entity, isCheckObjectCleanly = true): Status
{
this.Append(obj, isCheckObjectCleanly);
@ -36,13 +36,16 @@ export class BlockTableRecord extends SymbolTableRecord
Append(entity: Entity, isCheckObjectCleanly = true)
{
if (this._db)
if (entity instanceof Dimension && !entity.DimStyle)
entity.DimStyle = this._db.DimStyleTable.Current;//设置默认的标注样式
this.EntityCol.Append(entity, isCheckObjectCleanly);
entity.Owner = this.objectId;
}
AppendEvent(entity: Entity)
{
}
/**添加实体实现(通过转发) */
AppendEvent(entity: Entity) { }
Remove(entity: Entity)
{

@ -7,6 +7,8 @@ import { CADFiler } from './CADFiler';
import { CADObject } from './CADObject';
import { CameraSnapshootRecord } from './CameraSnapshoot/CameraSnapshootRecord';
import { DeepCloneFiler } from './DeepCloneFiler';
import { DimStyleRecord } from './DimStyle/DimStyleRecord';
import { DimStyleTable } from './DimStyle/DimStyleTable';
import { Entity } from './Entity/Entity';
import { GroupTable } from './GroupTable';
import { HistoricManage } from './HistoricManage';
@ -39,6 +41,7 @@ export class Database
TemplateTable: TemplateTable;
GroupTable: GroupTable;
ProcessingGroupTable: ProcessingGroupTable;
DimStyleTable: DimStyleTable;
//模型空间(里面有模型空间的实体列表)
ModelSpace: BlockTableRecord;
@ -72,8 +75,38 @@ export class Database
this.hm = new HistoricManage().SetDefaultDb(this);
this.hm.Enable = false;
this.LayoutSpace = new BlockTableRecord().SetOwnerDatabase(this);
this.DimStyleTable = new DimStyleTable().SetOwnerDatabase(this);
if (buildDefaultDrawing)
{
this.InitDimStyle();
this.InitMaterial();
this.InitLight();
this.SettingDefaultStyleAndMaterial();
}
this.hm.Enable = !disableHistoric;
//100以内的id是系统保留id,默认初始化内部对象.
this.idIndex = 100;
}
private InitDimStyle()
{
this.idIndex = 60;
let styleRd = new DimStyleRecord;
styleRd.Name = "默认";
this.DimStyleTable.Add(styleRd);
this.DimStyleTable.Current = styleRd.Id;
}
private InitMaterial()
{
this.idIndex = 70;
this.DefaultMaterial = new PhysicalMaterialRecord();
@ -91,16 +124,6 @@ export class Database
this.MaterialTable.Add(this.DefaultMaterial);
texture.Update();
this.SettingDefaultMaterial();
//初始化灯光
this.InitLight();
}
this.hm.Enable = !disableHistoric;
//100以内的id是系统保留id,默认初始化内部对象.
this.idIndex = 100;
}
private InitLight()
@ -118,7 +141,7 @@ export class Database
this.Lights.Add(this.HemisphereLight);
}
SettingDefaultMaterial()
SettingDefaultStyleAndMaterial()
{
if (!this.defaultDatabase)
return;
@ -126,6 +149,9 @@ export class Database
this.DefaultMaterial = this.GetObjectId(71)?.Object as PhysicalMaterialRecord ?? this.DefaultMaterial;
this.DefaultMaterial.Update();
HostApplicationServices.DefaultMeshMaterial = this.DefaultMaterial.Material;
let styleRd = this.GetObjectId(60)?.Object as DimStyleRecord;
HostApplicationServices.CurrentDimStyle = styleRd.Id;
}
Destroy()
@ -139,6 +165,7 @@ export class Database
this.GroupTable.Destroy();
this.Lights.Destroy();
this.ProcessingGroupTable.Destroy();
this.DimStyleTable.Destroy();
this.hm.Destroy();
this.CameraSnapshoots.length = 0;
this.hm.historyRecord.length = 0;
@ -151,6 +178,7 @@ export class Database
this.GroupTable.SetOwnerDatabase(this);
this.Lights.SetOwnerDatabase(this);
this.ProcessingGroupTable.SetOwnerDatabase(this);
this.DimStyleTable.SetOwnerDatabase(this);
this.hm.SetDefaultDb(this);
this.LayoutSpace.SetOwnerDatabase(this);
this.idIndex = 100;
@ -160,7 +188,7 @@ export class Database
FileWrite(file = new CADFiler): CADFiler
{
file.Write(8);//ver;
file.Write(9);//ver;
file.Write(this.idIndex);
this.ModelSpace.WriteFile(file);
this.TextureTable.WriteFile(file);
@ -177,6 +205,7 @@ export class Database
for (let r of this.CameraSnapshoots)
r.WriteFile(file);
this.DimStyleTable.WriteFile(file);
return file;
}
FileRead(file: CADFiler)
@ -234,7 +263,16 @@ export class Database
}
}
this.SettingDefaultMaterial();
if (ver > 8)
this.DimStyleTable.ReadFile(file);
else
{
let indexBak = this.idIndex;
this.InitDimStyle();
this.idIndex = indexBak;
}
this.SettingDefaultStyleAndMaterial();
this.hm.doing = false;
Entity.__ReadFileIng__ = false;

@ -0,0 +1,100 @@
import { AutoRecord } from "../AutoRecord";
import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler";
import { SymbolTableRecord } from "../SymbolTableRecord";
//ref https://ezdxf.readthedocs.io/en/stable/dxfinternals/tables/dimstyle_table.html
export enum DimTextPosDir
{
Top = 1,//上
Out = 2,//外部
}
/**
*
*/
@Factory
export class DimStyleRecord extends SymbolTableRecord
{
/** 如果设置为 1延长线(脚线)具有固定长度 DIMFXLON 290 */
@AutoRecord DIMFXLON: boolean = true;//1
/** DIMFXL 49 尺寸线下方的延长线长度如果固定DIMFXLON 为 1DIMEXE 定义尺寸线上方的长度 */
@AutoRecord DIMFXL: number = 100;
/** 控制尺寸中换算单位的显示 DIMALT 170 */
@AutoRecord DIMALT: boolean = true;//2
//
/** 控制换算单位的小数位数。如果打开 DIMALTDIMALTD 会设置交替测量中小数点右侧显示的位数。 DIMALTD 171 */
@AutoRecord DIMALTD: number = 2;//控制对齐标注的小数位精度
@AutoRecord DIMADEC: number = 2;//控制在角度尺寸中显示的精度位置的数量。
/** DIMASZ 41 控制尺寸线和引线箭头的大小。还控制钩线的大小。箭头大小的倍数决定尺寸线和文本是否应适合尺寸界线。如果由 DIMBLK 设置DIMASZ 也用于缩放箭头块。当 DIMTSZ 不为零时DIMASZ 无效。 */
@AutoRecord DIMASZ: number = 10;
/**147 尺寸线距离文字的距离(从尺寸线偏移) */
@AutoRecord DIMGAP: number = 2;
/**42 指定尺寸界线与原点的偏移距离。对于固定长度的延长线,此值确定最小偏移量。 */
@AutoRecord DIMEXO: number = 20;
/**43 */
@AutoRecord DIMDLI: number = 20;
/**44 肩膀上面的延伸线长度 */
@AutoRecord DIMEXE: number = 20;
/** 140 文字高度 */
@AutoRecord DIMTXT: number = 60;
/**77 控制文本相对于尺寸线的垂直位置。 */
@AutoRecord DIMTAD: DimTextPosDir = DimTextPosDir.Out;
// DIMTMOVE 279 设置标注文字移动规则。0 = 使用尺寸文本移动尺寸线 1 = 在移动尺寸文本时添加引线 2 = 允许文本在没有引线的情况下自由移动
//#region -------------------------File-------------------------
//对象从文件中读取数据,初始化自身
override ReadFile(file: CADFiler)
{
let ver = file.Read();
super.ReadFile(file);
let bitV = file.Read() as number;
this.DIMFXLON = (bitV & 1) > 0;
this.DIMALT = (bitV & 2) > 0;
this.DIMFXL = file.Read();
this.DIMALTD = file.Read();
this.DIMASZ = file.Read();
this.DIMGAP = file.Read();
this.DIMEXO = file.Read();
this.DIMDLI = file.Read();
this.DIMEXE = file.Read();
this.DIMTXT = file.Read();
this.DIMTAD = file.Read();
}
//对象将自身数据写入到文件.
override WriteFile(file: CADFiler)
{
file.Write(1);
super.WriteFile(file);
let bitV = 0;//压缩布尔值到里面
if (this.DIMFXLON) bitV += 1;
if (this.DIMALT) bitV += 2;
file.Write(bitV);
file.Write(this.DIMFXL);
file.Write(this.DIMALTD);
file.Write(this.DIMASZ);
file.Write(this.DIMGAP);
file.Write(this.DIMEXO);
file.Write(this.DIMDLI);
file.Write(this.DIMEXE);
file.Write(this.DIMTXT);
file.Write(this.DIMTAD);
}
//#endregion
}

@ -0,0 +1,27 @@
import { CADFiler } from "../CADFiler";
import { ObjectId } from "../ObjectId";
import { Factory } from "./../CADFactory";
import { SymbolTable } from "./../SymbolTable";
@Factory
export class DimStyleTable extends SymbolTable
{
Current: ObjectId;
//#region -------------------------File-------------------------
//对象从文件中读取数据,初始化自身
override ReadFile(file: CADFiler)
{
let ver = file.Read();
super.ReadFile(file);
this.Current = file.ReadObjectId();
}
//对象将自身数据写入到文件.
override WriteFile(file: CADFiler)
{
file.Write(1);
super.WriteFile(file);
file.WriteObjectId(this.Current);
}
//#endregion
}

@ -0,0 +1,26 @@
export enum DimStyleKeyCode
{
DIMEXO = 20,
/**如果设置为 1延长线具有固定长度 */
DIMFXL = 49,
/**延长线长度 */
DIMFXLON = 290,
/**控制尺寸中换算单位的显示 */
DIMALT = 170,
/**控制换算单位的小数位数。 */
DIMALTD = 171,
DIMADEC = 179,
/**箭头尺寸 */
DIMASZ = 41,
DIMEXE = 44,
DIMTAD = 77,
DIMTXT = 140,
}
//enum to string
// let code = DimStyleKeyCode[DimStyleKeyCode.DIMALT];
//enum keys
// type keys = keyof typeof DimStyleKeyCode

@ -8,11 +8,12 @@ import { reviseMirrorMatrix } from "../../Common/Matrix4Utils";
import { FixedNotZero, FixIndex } from "../../Common/Utils";
import { ObjectSnapMode } from "../../Editor/ObjectSnapMode";
import { BufferGeometryUtils } from "../../Geometry/BufferGeometryUtils";
import { angle, equaln, equalv3 } from "../../Geometry/GeUtils";
import { angle, equaln, equalv3, polar } from "../../Geometry/GeUtils";
import { IntersectOption } from "../../GraphicsSystem/IntersectWith";
import { RenderType } from "../../GraphicsSystem/RenderType";
import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler";
import { DimStyleKeyCode } from "../DimStyle/DimstyleKeyCodeEnum";
import { Arc } from "../Entity/Arc";
import { Line } from "../Entity/Line";
import { TextAligen } from "../Text/Text";
@ -40,9 +41,16 @@ export class LineAngularDimension extends Dimension
this._Text.Height = HostApplicationServices.dimTextHeight;
}
protected GetString()
override get FractionDigits() { return this.GetDimStyleValue(DimStyleKeyCode.DIMADEC); }
override set FractionDigits(length: number)
{
this.SetDimStyleOverrideValue(DimStyleKeyCode.DIMADEC, length);
}
protected GetPrimitiveString()
{
return FixedNotZero(MathUtils.radToDeg(this._Arc.AllAngle), this._FractionDigits) + "°";
return FixedNotZero(MathUtils.radToDeg(this._Arc.AllAngle), this.FractionDigits) + "°";
}
UpdateDimData(l1sp: Vector3, l1ep: Vector3, l2sp: Vector3, l2ep: Vector3, dimp: Vector3)
@ -318,10 +326,13 @@ export class LineAngularDimension extends Dimension
this._Text.AutoUpdate = false;//更新标记
this._Text.Height = this._TextSize;
this._Text.Height = this.TextSize;
this._Text.TextString = this.TextString;
this._Text.Position = this._Arc.GetPointAtParam(0.5);
this._Text.TextRotation = this._Arc.GetAngleAtParam(0.5) % (Math.PI) - Math.PI / 2;
let midAngle = this._Arc.GetAngleAtParam(0.5);
this._Text.Position = polar(this._Arc.GetPointAtParam(0.5), midAngle, 10);
this._Text.TextRotation = midAngle % (Math.PI) - Math.PI / 2;
this._Text.TextAligen = midAngle > Math.PI ? TextAligen.Top : TextAligen.Down;
this._Text.AutoUpdate = true;//更新标记
this._Text.DeferUpdate();
@ -378,20 +389,23 @@ export class LineAngularDimension extends Dimension
this._L2EndPoint.fromArray(file.Read());
this._DimPoint.fromArray(file.Read());
if (ver > 1) this._TextString = file.Read();
if (ver > 2) this._TextSize = file.Read();
if (ver > 2 && ver < 4) this.TextSize = file.Read();
if (ver > 3) this.ReadDimStyle(file);
}
//对象将自身数据写入到文件.
WriteFile(file: CADFiler)
{
super.WriteFile(file);
file.Write(3);
file.Write(4);
file.Write(this._L1StartPoint.toArray());
file.Write(this._L1EndPoint.toArray());
file.Write(this._L2StartPoint.toArray());
file.Write(this._L2EndPoint.toArray());
file.Write(this._DimPoint.toArray());
file.Write(this._TextString);
file.Write(this._TextSize);
this.WriteDimStyle(file);
}
//#endregion

@ -4,53 +4,41 @@ import { LineGeometry } from "three/examples/jsm/lines/LineGeometry";
import { HostApplicationServices } from "../../ApplicationServices/HostApplicationServices";
import { AddEntityDrawObject } from "../../Common/AddEntityDrawObject";
import { ColorMaterial } from "../../Common/ColorPalette";
import { safeEval } from "../../Common/eval";
import { reviseMirrorMatrix } from "../../Common/Matrix4Utils";
import { UpdateDraw } from "../../Common/Status";
import { FixedNotZero } from "../../Common/Utils";
import { ObjectSnapMode } from "../../Editor/ObjectSnapMode";
import { BufferGeometryUtils } from "../../Geometry/BufferGeometryUtils";
import { angle, angleAndX, AsVector2, equaln, equalv3, isParallelTo, midPoint, ZAxis } from "../../Geometry/GeUtils";
import { angle, angleAndX, AsVector2, AsVector3, equaln, equalv3, isParallelTo, midPoint, ZAxis } from "../../Geometry/GeUtils";
import { ROTATE_MTX2 } from "../../Geometry/RotateUV";
import { RenderType } from "../../GraphicsSystem/RenderType";
import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler";
import { DimStyleKeyCode } from "../DimStyle/DimstyleKeyCodeEnum";
import { DimTextPosDir } from "../DimStyle/DimStyleRecord";
import { Line } from "../Entity/Line";
import { Polyline } from "../Entity/Polyline";
import { ObjectId } from "../ObjectId";
import { TextAligen } from "../Text/Text";
import { Dimension } from "./Dimension";
import { GetDimLineMaterial } from "./GetDimLineMaterial";
/**用于提供捕捉的多段线 */
let snapPolyline = new Polyline([{ pt: new Vector2, bul: 0 }, { pt: new Vector2, bul: 0 }, { pt: new Vector2, bul: 0 }, { pt: new Vector2, bul: 0 }]);
interface LeadOutLinePts
{
dragPt: Vector3;
endPt: Vector3;
}
interface DefaultValue
{
offset: Vector2;
isFlipped: boolean;
}
/**
*
* (线 LinearDimension)
* @class AlignedDimension
*/
@Factory
export class AlignedDimension extends Dimension
{
//引线
private _LeadOutLine = new Polyline();
private _LeadOutOffsetY = 72;
private _LeadOutOffsetX = 30;
private _DefaultVal: DefaultValue = { offset: new Vector2(30, 72), isFlipped: false };
//引线的拖拽点和终点
private _LeadOutPts: LeadOutLinePts = { dragPt: midPoint(this._ArmP1, this._ArmP2), endPt: new Vector3() };
//引线是否反向(往左伸/往右伸)
private _LeadOutIsFlipped: boolean = false;
//是否由拖拽更新_LeadOutPts.dragPt. 关系到引线的update
private isDragLeadOutPt: boolean = false;
//引线(用于绘制)
private _LeadLine = new Polyline();
/**引线的起始位置,在引线坐标系+使用中点 */
private _LeadPos: Vector2 = new Vector2(30, this.TextSize * 1.2);
/**构造函数提供的点在对象坐标系内部 */
constructor(
//针脚
protected _FootP1: Vector3 = new Vector3(),
@ -58,64 +46,58 @@ export class AlignedDimension extends Dimension
//肩膀
protected _ArmP1: Vector3 = new Vector3(),
protected _ArmP2: Vector3 = new Vector3(),
protected _TextRotation: number = undefined,
//是否显示引线
protected _LeadOutVisible: boolean = true,
protected _TextRotation: number = null,
//当尺寸线放不下文字时,使用引线
protected _UseLead: boolean = true,
)
{
super();
this._Text.TextAligen = TextAligen.Down;
this._Text.Height = HostApplicationServices.dimTextHeight;
this._ArmP1.setZ(0);
this._ArmP2.setZ(0);
}
set Material(materialId: ObjectId) { }
get Distance() { return this._ArmP1.distanceTo(this._ArmP2); }
get FootP1() { return this._FootP1.clone().applyMatrix4(this._Matrix); }
set FootP1(v: Vector3)
{
this._FootP1.copy(v).applyMatrix4(this.OCSInv);
this.Update();
}
get FootP1()
{
return this._FootP1.clone().applyMatrix4(this._Matrix);
}
get FootP2() { return this._FootP2.clone().applyMatrix4(this._Matrix); }
set FootP2(v: Vector3)
{
this._FootP2.copy(v).applyMatrix4(this.OCSInv);
this.Update();
}
get FootP2()
{
return this._FootP2.clone().applyMatrix4(this._Matrix);
}
get ArmP1() { return this._ArmP1.clone().applyMatrix4(this._Matrix); }
set ArmP1(v: Vector3)
{
this.WriteAllObjectRecord();
this._ArmP1.copy(v).applyMatrix4(this.OCSInv);
this._ArmP1.setZ(0);
this.Update();
}
get ArmP1()
{
return this._ArmP1.clone().applyMatrix4(this._Matrix);
}
get ArmP2() { return this._ArmP2.clone().applyMatrix4(this._Matrix); }
set ArmP2(v: Vector3)
{
this.WriteAllObjectRecord();
this._ArmP2.copy(v).applyMatrix4(this.OCSInv);
this._ArmP2.setZ(0);
this.Update();
}
get ArmP2()
{
return this._ArmP2.clone().applyMatrix4(this._Matrix);
}
get TextPosition()
{
return midPoint(this._ArmP1, this._ArmP2).applyMatrix4(this._Matrix);
}
get TextPosition() { return midPoint(this._ArmP1, this._ArmP2).applyMatrix4(this._Matrix); }
/**实际上这个是BasePoint 用来定位尺寸线的位置 */
set TextPosition(p: Vector3)
{
p = p.clone().applyMatrix4(this.OCSInv);
let l = new Line(this._ArmP1.clone(), this._ArmP2.clone());
p.setZ(this._ArmP1.z);
this.WriteAllObjectRecord();
p = p.clone().applyMatrix4(this.OCSInv).setZ(0);
let l = new Line(this._ArmP1, this._ArmP2);
let cp = l.GetClosestPointTo(p, true);
let v = p.clone().sub(cp);
@ -129,59 +111,22 @@ export class AlignedDimension extends Dimension
get DalUcs()
{
let dalUcs = new Matrix4();
if (!equaln(this._ArmP1.distanceTo(this._ArmP2), 0))
{
let vx = this._ArmP2.clone().sub(this._ArmP1);
if (equaln(this._ArmP1.x, this._ArmP2.x))
if (!equalv3(this._ArmP1, this._ArmP2))
{
if (this._ArmP1.y < this._ArmP2.y)
vx.negate();
}
else if (this._ArmP1.x < this._ArmP2.x)
vx.negate();
if (isParallelTo(vx, ZAxis))
return new Matrix4().setPosition(this._FootP1);
let vy = vx.clone().cross(ZAxis);
dalUcs = new Matrix4().makeBasis(vx.normalize(), vy.normalize(), ZAxis);
dalUcs.setPosition(this._FootP1);
let vy = this.ParseTopDir()[0];
let vx = new Vector3().crossVectors(vy, ZAxis);
dalUcs = new Matrix4().makeBasis(vx, vy, ZAxis);
}
dalUcs.setPosition(midPoint(this._ArmP1, this._ArmP2));
return dalUcs;
}
RaiseFooters(num: number)
{
let dalucs = this.DalUcs;
let dalUcsInv = new Matrix4().getInverse(dalucs);
let p = new Vector3(0, num, 0);
let f1 = this._FootP1.clone().applyMatrix4(dalucs);
let f2 = this._FootP2.clone().applyMatrix4(dalucs);
let a1 = this._ArmP1.clone().applyMatrix4(dalucs);
if (a1.y < f1.y)
p.negate();
this._FootP1 = f1.add(p).applyMatrix4(dalUcsInv);
this._FootP2 = f2.add(p).applyMatrix4(dalUcsInv);
this.Update();
}
set TextRotation(angle: number)
{
this._TextRotation = angle;
this.Update();
}
set TextAligen(al: TextAligen)
{
if (al !== this._Text.TextAligen)
{
this.WriteAllObjectRecord();
this._Text.TextAligen = al;
}
}
get Text()
{
if (!this._Text.TextString)
@ -190,9 +135,9 @@ export class AlignedDimension extends Dimension
return this._Text;
}
protected GetString(): string
protected GetPrimitiveString(): string
{
return FixedNotZero(this._ArmP1.distanceTo(this._ArmP2), this._FractionDigits);
return FixedNotZero(this._ArmP1.distanceTo(this._ArmP2), this.FractionDigits);
}
get BoundingBox()
@ -204,77 +149,65 @@ export class AlignedDimension extends Dimension
return snapPolyline.BoundingBox;
}
set LeadOutVisible(visible: boolean)
get LeadVisible() { return this._UseLead; }
/**设置引线可见 */
set LeadVisible(visible: boolean)
{
if (this._LeadOutVisible === visible) return;
if (this._UseLead === visible) return;
this.WriteAllObjectRecord();
this._LeadOutVisible = visible;
this._UseLead = visible;
this.Update();
}
//引线朝右视为未翻转
set LeadOutFlipped(isFlipped: boolean)
set LeadInLeft(isLeft: boolean)
{
if (this._LeadOutIsFlipped === isFlipped) return;
this.WriteAllObjectRecord();
this._LeadOutIsFlipped = isFlipped;
this.Update();
}
if (this._LeadPos.x < 0 === isLeft)
return;
get LeadOutFlipped()
{
return this._LeadOutIsFlipped;
this.FlippeLead();
}
toggleLeadOutVisible()
/**切换引线可见性 */
ToggleLeadVisible()
{
this.WriteAllObjectRecord();
this.LeadOutVisible = !this._LeadOutVisible;
this.LeadVisible = !this._UseLead;
}
toggleLeadOutFlipped()
/**切换引线翻转 */
FlippeLead()
{
this.WriteAllObjectRecord();
this.LeadOutFlipped = !this._LeadOutIsFlipped;
this._LeadPos.x = -this._LeadPos.x;
this.Update();
}
set LeadOutOffsetY(size: number)
get LeadY() { return this._LeadPos.y; }
/**引线偏移 */
set LeadY(y: number)
{
if (this._LeadOutOffsetY === size) return;
if (this.LeadY === y) return;
this.WriteAllObjectRecord();
this._LeadOutOffsetY = size;
this._LeadPos.y = y;
this.Update();
}
get LeadOutOffsetY()
{
return this._LeadOutOffsetY;
}
set LeadOutOffsetX(size: number)
get LeadX() { return this._LeadPos.x; }
set LeadX(x: number)
{
if (this._LeadOutOffsetX === size) return;
if (this.LeadX === x) return;
this.WriteAllObjectRecord();
this._LeadOutOffsetX = size;
this._LeadPos.x = x;
this.Update();
}
get LeadOutOffsetX()
{
return this._LeadOutOffsetX;
}
set DefaultValue(val: DefaultValue)
{
this._DefaultVal = val;
this._LeadOutOffsetX = val.offset.x;
this._LeadOutOffsetY = val.offset.y;
this.LeadOutFlipped = val.isFlipped;
}
get DefaultValue()
/**设置引线数据 */
SetLeadData(offset: Vector2, isFlipped = false)
{
return this._DefaultVal;
this.WriteAllObjectRecord();
this._LeadPos.copy(offset);
if (isFlipped) this._LeadPos.x *= -1;
this.Update();
}
Explode()
@ -287,13 +220,17 @@ export class AlignedDimension extends Dimension
new Line(this._ArmP2.clone(), this._FootP2.clone()),
this._Text.Clone()
];
if (!equalv3(this._LeadOutPts.dragPt, midPoint(this._ArmP1, this._ArmP2)))
if (this._UseLead && this.NeedLead)
{
let mp = midPoint(this._ArmP1, this._ArmP2);
res.push(
new Line(midPoint(this._ArmP1, this._ArmP2), this._LeadOutPts.dragPt.clone()),
new Line(this._LeadOutPts.dragPt.clone(), this._LeadOutPts.endPt.clone())
new Line(mp.clone(), AsVector3(this._LeadPos).add(mp)),
new Line(AsVector3(this._LeadPos).add(mp), AsVector3(this._LeadPos).add(mp).add(new Vector3(this.TextBoxWidth, 0, 0)))
);
}
return res.map(en => en.ApplyMatrix(this._Matrix));
}
protected ApplyMirrorMatrix(m: Matrix4)
{
this.WriteAllObjectRecord();
@ -312,6 +249,7 @@ export class AlignedDimension extends Dimension
this.Update(UpdateDraw.Geometry);
return this;
}
Clone(): this
{
let ent = super.Clone();
@ -337,7 +275,7 @@ export class AlignedDimension extends Dimension
}
else
line = new TLine(
BufferGeometryUtils.CreateFromPts([this._FootP1, this._FootP2, this._ArmP1, this._ArmP2]),
BufferGeometryUtils.CreateFromPts([this._FootP1, this._FootP2, this._ArmP1, this._ArmP2, this._ArmP2, this._ArmP2]),
colorMaterial
);
@ -351,31 +289,101 @@ export class AlignedDimension extends Dimension
return obj;
}
ParseTopDir(): [Vector3, Vector3, Vector3]
{
let [f1, f2, a1, a2] = [this._FootP1, this._FootP2, this._ArmP1, this._ArmP2].map(p => p.clone().setZ(0));
let armV = a1.clone().sub(a2);
//#region 头部延伸线
let topDir1: Vector3, topDir2: Vector3;//↑头顶部的向量 用来突出肩膀(文字或者肩膀的线)
if (!equalv3(f1, a1))
topDir1 = a1.clone().sub(f1).normalize();
if (!equalv3(f2, a2))
topDir2 = a2.clone().sub(f2).normalize();
let topDir = topDir1 ?? topDir2;
if (!topDir)
{
topDir = armV.clone().normalize();
ROTATE_MTX2.applyVector(topDir);
}
if (!topDir1) topDir1 = topDir;
if (!topDir2) topDir2 = topDir;
return [topDir, topDir1, topDir2];
}
UpdateDrawObject(renderType: RenderType, obj: Object3D)
{
obj.remove(...obj.children.slice(3));
let [line, arrow1, arrow2] = obj.children;
let arrowSize = 10;
let [f1, f2, a1, a2] = [this._FootP1, this._FootP2, this._ArmP1, this._ArmP2].map(p => p.clone().setZ(0));
let armV = a1.clone().sub(a2);
//#region 头部延伸线
let [topDir, topDir1, topDir2] = this.ParseTopDir();
let topExt = this.GetDimStyleValue(DimStyleKeyCode.DIMEXE) ?? 10;
let a11 = topDir1.clone().multiplyScalar(topExt).add(a1);
let a21 = topDir2.clone().multiplyScalar(topExt).add(a2);
//#endregion
//#region 固定延伸线的尺寸
let length1 = f1.distanceTo(a1);
let length2 = f2.distanceTo(a2);
let newLength1 = length1;
let newLength2 = length2;
let dimexo = this.GetDimStyleValue(DimStyleKeyCode.DIMEXO) ?? 20;//脚线的偏移距离
newLength1 = Math.max(0, newLength1 - dimexo);
newLength2 = Math.max(0, newLength2 - dimexo);
if (this.GetDimStyleValue(DimStyleKeyCode.DIMFXLON))//固定脚线长度
{
let fixLength = this.GetDimStyleOverrideValue(DimStyleKeyCode.DIMFXL) ?? 100;//固定脚线长度
if (newLength1 > fixLength)
newLength1 = fixLength;
if (newLength2 > fixLength)
newLength2 = fixLength;
}
if (newLength1 !== length1)
f1.sub(a1).normalize().multiplyScalar(newLength1).add(a1);
if (newLength2 !== length2)
f2.sub(a2).normalize().multiplyScalar(newLength2).add(a2);
//#endregion
//#region 更新线部分
let linePts = [f1, a11, a1, a2, a21, f2];
if (renderType === RenderType.WireframePrint)
{
arrowSize *= HostApplicationServices.lineWidth * 0.5;
const geometry = (<Line2>line).geometry;
let nums: number[] = [];
for (let p of [this._FootP1, this._ArmP1, this._ArmP2, this._FootP2])
for (let p of linePts)
nums.push(p.x, p.y, p.z);
geometry.setPositions(nums);
}
else
BufferGeometryUtils.UpdatePts((<TLine>line).geometry as BufferGeometry, [this._FootP1, this._ArmP1, this._ArmP2, this._FootP2], true);
BufferGeometryUtils.UpdatePts((<TLine>line).geometry as BufferGeometry, linePts, true);
//#endregion
//#region 箭头部分
let arrowSize = this.GetDimStyleValue(DimStyleKeyCode.DIMASZ) ?? 10;
if (renderType === RenderType.WireframePrint)//在打印模式下,改变箭头的大小?
arrowSize *= HostApplicationServices.lineWidth * 0.5;
arrow1.scale.set(arrowSize, arrowSize, arrowSize);
arrow2.scale.set(arrowSize, arrowSize, arrowSize);
let armV = this._ArmP1.clone().sub(this._ArmP2);
let armAn = angle(armV);
arrow1.position.copy(this._ArmP1);
arrow2.position.copy(this._ArmP2);
let armAn = angle(armV);
if (this._ArmP1.distanceTo(this._ArmP2) < 36)
{
arrow1.rotation.z = armAn + Math.PI / 2;
@ -388,95 +396,109 @@ export class AlignedDimension extends Dimension
}
arrow1.updateMatrix();
arrow2.updateMatrix();
//#endregion
//#region 文字和引线
//更新引线this._LeadOutLine 并返回新的字体位置
let textPos = this.UpdateLeadOutLine(renderType);
if (this._LeadOutLine.EndParam > 0 && this._LeadOutLine.Visible)
AddEntityDrawObject(obj, this._LeadOutLine, renderType);
let textPos = this.UpdateLeadLine();
let hasLead = this._UseLead && this.NeedLead;
let textPosDir = this.GetDimStyleValue(DimStyleKeyCode.DIMTAD) as DimTextPosDir ?? DimTextPosDir.Out;
if (textPosDir === DimTextPosDir.Out)//文字在尺寸线(或引线)外部
{
let textDir = topDir;//文字相对于基准线(引线) 的位置方向向量
if (hasLead && this._LeadPos.y < 0)//引线方向和头部方向相反 则逆转方向(dir = 引线的朝向)
textDir = textDir.clone().negate();
if (equaln(textDir.y, 0))//水平标注
this.Text.TextAligen = textDir.x > 0 ? TextAligen.Top : TextAligen.Down;
else
this._Text.TextAligen = textDir.y < 0 ? TextAligen.Top : TextAligen.Down;
textPos.add(textDir.multiplyScalar(10));
}
else//文字在尺寸线(或引线)上方
{
this._Text.TextAligen = TextAligen.Down;
textPos.add(topDir.multiplyScalar(10));
}
if (hasLead)
AddEntityDrawObject(obj, this._LeadLine, renderType);
this.UpdateText(textPos);
AddEntityDrawObject(obj, this._Text, renderType);
this.isDragLeadOutPt = false;
//#endregion
}
get NeedLead(): boolean
{
let distance = this._ArmP1.distanceTo(this._ArmP2);
let textBoxWidth = this.TextBoxWidth;
let needLead = (distance < textBoxWidth - 2) && !(equaln(distance, 0));//文字宽度是否比托盘更宽 是 则需要引线
return needLead;
}
/**
* 线textPosition
* @returns textPosition(Vector3)
* @memberof AlignedDimension
*/
UpdateLeadOutLine(renderType: RenderType): Vector3
UpdateLeadLine(): Vector3
{
let textPosition: Vector3 = midPoint(this._ArmP1, this._ArmP2);
let armMidP: Vector3 = midPoint(this._ArmP1, this._ArmP2);
let textPosition = armMidP;
let distance = this._ArmP1.distanceTo(this._ArmP2);
let distanceStr = FixedNotZero(distance, 2);
let strWidth = distanceStr.length * (~~(Math.abs(this.TextSize) / 2));//文字总宽度
let needLeadOut = (safeEval(distanceStr) < strWidth + 1e-6) && !(equaln(distance, 0));//文字宽度是否比托盘更宽 是 则需要引线
if (this._LeadOutVisible && needLeadOut) //引线可见且需要引线
if (this._UseLead && this.NeedLead) //引线可见且需要引线
{
let dalUcs = this.DalUcs;
let dalUcsInv = new Matrix4().getInverse(dalUcs);
let textWidthVec = new Vector3(strWidth);
let isLeft = (v) => { return v.x < midPoint(this._ArmP1, this._ArmP2).applyMatrix4(dalUcs).x; };
//确定引线的点的位置
if (this.isDragLeadOutPt)//是否拖拽了dragPt(拖拽dragPt需要更新endPt)
{
let dragPtInDalUcs = this._LeadOutPts.dragPt.clone().applyMatrix4(dalUcs);
let isleft = isLeft(dragPtInDalUcs.clone());
if (isleft)//已经拖过中线 更新endPt 改变IsFlipped
this._LeadOutPts.endPt = dragPtInDalUcs.clone().sub(textWidthVec);
else
this._LeadOutPts.endPt = dragPtInDalUcs.clone().add(textWidthVec);
this._LeadOutIsFlipped = !isleft;
}
else //没有拖拽
{
this._LeadOutPts.dragPt = textPosition.clone().applyMatrix4(dalUcs).add(new Vector3(this._LeadOutIsFlipped ? this._LeadOutOffsetX : -this._LeadOutOffsetX, this._LeadOutOffsetY));
if (isLeft(this._LeadOutPts.dragPt))
this._LeadOutPts.endPt = this._LeadOutPts.dragPt.clone().sub(textWidthVec);
else
this._LeadOutPts.endPt = this._LeadOutPts.dragPt.clone().add(textWidthVec);
this._LeadOutPts.dragPt.applyMatrix4(dalUcsInv);
}
this._LeadOutPts.endPt.applyMatrix4(dalUcsInv);
let leadP1 = AsVector3(this._LeadPos).applyMatrix4(dalUcs);
let leadP2 = AsVector3(this._LeadPos).add(new Vector3(this.TextBoxWidth * Math.sign(this._LeadPos.x))).applyMatrix4(dalUcs);
textPosition.setFromMatrixColumn(dalUcs, 3);
this._LeadOutLine.AutoUpdate = false;
this._LeadOutLine.LineData = [textPosition, this._LeadOutPts.dragPt, this._LeadOutPts.endPt].map(p => { return { pt: AsVector2(p), bul: 0 }; });
this._LeadOutLine.Position = new Vector3(0, 0, textPosition.z);
this._LeadOutLine.ColorIndex = this.ColorIndex;
this._LeadOutLine.Visible = true;
this._LeadOutLine.AutoUpdate = true;
this._LeadOutLine.DeferUpdate();
this._LeadLine.AutoUpdate = false;
this._LeadLine.IsEmbedEntity = true;//使它可以捕捉
this._LeadLine.LineData = [textPosition, leadP1, leadP2].map(p => { return { pt: AsVector2(p), bul: 0 }; });
this._LeadLine.ColorIndex = this.ColorIndex;
this._LeadLine.Visible = true;//可见性设置
this._LeadLine.AutoUpdate = true;
this._LeadLine.DeferUpdate();
textPosition = midPoint(this._LeadOutPts.dragPt, this._LeadOutPts.endPt);
textPosition.copy(leadP1).add(leadP2).divideScalar(2);//引线中点
}
else //引线不可见或不需要引线
{
//使引线不可见 并将dragPt隐藏于托盘中点
this._LeadOutPts.dragPt = midPoint(this._ArmP1, this._ArmP2);
this._LeadOutLine.Visible = false;
this._LeadLine.Visible = false;//可见性设置
}
return textPosition;
}
UpdateText(pos?: Vector3)
UpdateText(textPos?: Vector3)
{
this._Text.AutoUpdate = false;
let textRo = this._TextRotation ?? angleAndX(this._ArmP1.clone().sub(this._ArmP2));
this._Text.TextString = this.TextString;
this._Text.Position = pos ?? midPoint(this._ArmP1, this._ArmP2);
this._Text.Position = textPos ?? midPoint(this._ArmP1, this._ArmP2);
this._Text.TextRotation = textRo;
this._Text.ColorIndex = this._Color;
this._Text.Height = this._TextSize;
this._Text.Height = this.TextSize * 0.923;//雅黑数字*0.923
this._Text.DeferUpdate();
this._Text.AutoUpdate = true;
}
protected OnChangeFootPt()
{
let l = new Line(this._FootP1.clone().setZ(0), this._FootP2.clone().setZ(0));
let cp = l.GetClosestPointTo(this._ArmP1, true);
let v = cp.subVectors(this._ArmP1, cp);
this._ArmP1.copy(this._FootP1.clone().add(v));
this._ArmP2.copy(this._FootP2.clone().add(v));
}
GetObjectSnapPoints(
snapMode: ObjectSnapMode,
pickPoint: Vector3,
@ -485,7 +507,24 @@ export class AlignedDimension extends Dimension
): Vector3[]
{
this.SetDataToTempPolyline();
return snapPolyline.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform);
let pts = snapPolyline.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform);
if (this._UseLead && this.NeedLead)
{
let dalUcs = this.DalUcs;
let armMidP: Vector3 = midPoint(this._ArmP1, this._ArmP2);
let leadP1 = AsVector3(this._LeadPos).applyMatrix4(dalUcs);
let leadP2 = AsVector3(this._LeadPos).add(new Vector3(this.TextBoxWidth * Math.sign(this._LeadPos.x))).applyMatrix4(dalUcs);
snapPolyline.LineData[0].pt.set(armMidP.x, armMidP.y);
snapPolyline.LineData[1].pt.set(leadP1.x, leadP1.y);
snapPolyline.LineData[2].pt.set(leadP2.x, leadP2.y);
snapPolyline.LineData[3].pt.set(leadP2.x, leadP2.y);
for (let p of snapPolyline.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform))
pts.push(p);
}
return pts;
}
private SetDataToTempPolyline()
@ -507,22 +546,23 @@ export class AlignedDimension extends Dimension
if (renderType === RenderType.WireframePrint)
return;
this.WriteAllObjectRecord();
let colorMat = GetDimLineMaterial(this, renderType);
this._LeadOutLine.ColorIndex = this._Color;
let mtl = GetDimLineMaterial(this, renderType);
this._LeadLine.ColorIndex = this._Color;
let [line, arrow1, arrow2] = obj.children;
(<Mesh>line).material = colorMat;
(<Mesh>arrow1).material = colorMat;
(<Mesh>arrow2).material = colorMat;
(<Mesh>line).material = mtl;
(<Mesh>arrow1).material = mtl;
(<Mesh>arrow2).material = mtl;
this._Text.ColorIndex = this._Color;
}
GetGripPoints(): Array<Vector3>
{
return [this._FootP1, this._FootP2, this._ArmP1, this._ArmP2, midPoint(this._ArmP1, this._ArmP2), this._LeadOutPts.dragPt].map(p =>
{
return p.clone().applyMatrix4(this._Matrix);
});
let pts = [this._FootP1, this._FootP2, this._ArmP1, this._ArmP2, midPoint(this._ArmP1, this._ArmP2)].map(p => p.clone().applyMatrix4(this._Matrix));
if (this._UseLead && this.NeedLead)
pts.push(AsVector3(this._LeadPos).applyMatrix4(this.DalUcs).applyMatrix4(this._Matrix));
return pts;
}
MoveGripPoints(indexList: number[], vec: Vector3)
{
this.WriteAllObjectRecord();
@ -531,17 +571,16 @@ export class AlignedDimension extends Dimension
let vec0 = vec.clone().applyMatrix4(inv0);
for (let i of indexList)
{
if (i === 5)
if (i === 5)//引线
{
let dalucs = this.DalUcs;
//开始拖拽引线dragPt
this.isDragLeadOutPt = true;
this._LeadOutPts.dragPt.add(vec0);
let calcV = this._LeadOutPts.dragPt.clone().applyMatrix4(dalucs).sub(midPoint(this._ArmP1, this._ArmP2).applyMatrix4(dalucs));
this._LeadOutOffsetY = calcV.y;
this._LeadOutOffsetX = Math.abs(calcV.x);
let dalUCS = this.DalUcs.setPosition(0, 0, 0);
dalUCS.getInverse(dalUCS);
vec0.applyMatrix4(dalUCS);
this._LeadPos.x += vec0.x;
this._LeadPos.y += vec0.y;
}
else if (i >= 2)
else if (i >= 2)//肩膀点 文字点(拽拖这个点不会把标注变大)
{
let p = this.TextPosition.add(vec).applyMatrix4(inv);
let l = new Line(this._ArmP1, this._ArmP2);
@ -550,24 +589,25 @@ export class AlignedDimension extends Dimension
this._ArmP1.add(v);
this._ArmP2.add(v);
this._LeadOutPts.dragPt.add(v);
}
else
else//脚线
{
if (i === 0)
this._FootP1.add(vec0);
else
this._FootP2.add(vec0);
this.ChangeFootPt();
this.OnChangeFootPt();
}
}
this.Update();
}
GetStretchPoints(): Array<Vector3>
{
return this.GetGripPoints();
}
MoveStretchPoints(indexList: Array<number>, vec: Vector3)
{
this.WriteAllObjectRecord();
@ -585,16 +625,6 @@ export class AlignedDimension extends Dimension
if (bChangeText)
this.MoveGripPoints([2], vec);
}
protected ChangeFootPt()
{
let l = new Line(this._FootP1, this._FootP2);
let cp = l.GetClosestPointTo(this._ArmP1, true);
let v = this._ArmP1.clone().sub(cp);
this._ArmP1.copy(this._FootP1.clone().add(v));
this._ArmP2.copy(this._FootP2.clone().add(v));
}
//#region -------------------------File-------------------------
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
@ -610,23 +640,86 @@ export class AlignedDimension extends Dimension
this._FootP2.fromArray(file.Read());
this._TextRotation = file.Read();
if (ver > 2) this._TextString = file.Read();
if (ver > 3)
if (ver < 7)//升级到版本7之后 标注统一在OCS平面绘制 (脚线允许在不同的平面)
{
//升级文件版本,将z轴移除
let z = this._ArmP1.z;
if (!equaln(z, 0))
{
this._Matrix.elements[12] += this._Matrix.elements[8] * z;
this._Matrix.elements[13] += this._Matrix.elements[9] * z;
this._Matrix.elements[14] += this._Matrix.elements[10] * z;
this._ArmP1.z = 0;
this._ArmP2.z = 0;
this._FootP1.z -= z;
this._FootP2.z -= z;
}
this.SetDimStyleOverrideValue(DimStyleKeyCode.DIMEXO, 0);//原始图纸脚线偏移为9
this.SetDimStyleOverrideValue(DimStyleKeyCode.DIMTAD, DimTextPosDir.Top);//原始图纸的文字位置为上
//虽然原始的标注也没有文字偏移,但是太丑了,所以不还原这个设置
}
if (ver > 3 && ver < 7)
{
this._UseLead = file.Read();
let leadFlipped = file.Read();
let leadStartP = new Vector3().fromArray(file.Read());
let y = file.Read();
let x = file.Read();
if (!leadFlipped) x = -x;
/**旧的引线坐标系 在OCS内部 */
const GetOldDalUcs = () =>
{
let dalUcs = new Matrix4();
if (!equalv3(this._ArmP1, this._ArmP2))
{
let vx = this._ArmP2.clone().sub(this._ArmP1).normalize();
if (equaln(this._ArmP1.x, this._ArmP2.x))
{
this._LeadOutVisible = file.Read();
this._LeadOutIsFlipped = file.Read();
this._LeadOutPts.dragPt.fromArray(file.Read());
this._LeadOutOffsetY = file.Read();
this._LeadOutOffsetX = file.Read();
if (this._ArmP1.y < this._ArmP2.y)
vx.negate();
}
if (ver > 4) this._TextSize = file.Read();
if (ver > 5) this._FractionDigits = file.Read() ?? HostApplicationServices.fractionDigitsType ?? 2;
else if (this._ArmP1.x < this._ArmP2.x)
vx.negate();
if (isParallelTo(vx, ZAxis))
return dalUcs.setPosition(midPoint(this._ArmP1, this._ArmP2));
let vy = vx.clone().cross(ZAxis);
dalUcs = new Matrix4().makeBasis(vx, vy, ZAxis);
dalUcs.setPosition(midPoint(this._ArmP1, this._ArmP2));
}
return dalUcs;
};
let p = new Vector3(x, y);
p.applyMatrix4(GetOldDalUcs());
let cs = this.DalUcs;
p.applyMatrix4(cs.getInverse(cs));
this._LeadPos.copy(p as any as Vector2);
}
if (ver > 4 && ver < 7) this.TextSize = file.Read();
if (ver > 5 && ver < 7) this.FractionDigits = file.Read() ?? 2;
if (ver >= 7)
{
this._UseLead = file.Read();
this._LeadPos.set(file.Read(), file.Read());
this.ReadDimStyle(file);
}
}
//对象将自身数据写入到文件.
WriteFile(file: CADFiler)
{
super.WriteFile(file);
file.Write(6);
file.Write(7);
file.Write(this._ArmP1.toArray());
file.Write(this._ArmP2.toArray());
file.Write(this._FootP1.toArray());
@ -634,14 +727,10 @@ export class AlignedDimension extends Dimension
file.Write(this._TextRotation);
file.Write(this._TextString);
file.Write(this._LeadOutVisible);
file.Write(this._LeadOutIsFlipped);
file.Write(this._LeadOutPts.dragPt.toArray());
file.Write(this._LeadOutOffsetY);
file.Write(this._LeadOutOffsetX);
file.Write(this._TextSize);
file.Write(this._FractionDigits);
file.Write(this._UseLead);
file.Write(this._LeadPos.x);
file.Write(this._LeadPos.y);
this.WriteDimStyle(file);
}
//#endregion
}

@ -52,9 +52,9 @@ export class ArcDimension extends Dimension
get TextRadiusAdd() { return this._TextRadiusAdd; }
protected GetString(): string
protected GetPrimitiveString(): string
{
return FixedNotZero(this._Arc.Length, this._FractionDigits);
return FixedNotZero(this._Arc.Length, this.FractionDigits);
}
//#region 拉伸相关
@ -185,7 +185,7 @@ export class ArcDimension extends Dimension
let textOCS = new Matrix4().makeRotationZ(ang + Math.PI * 3 / 2).setPosition(textP);
this._Text.TextAligen = TextAligen.Down;
this._Text.OCS = textOCS;
this._Text.Height = this._TextSize;
this._Text.Height = this.TextSize;
}
UpdateDrawObjectMaterial(type: RenderType, obj: Object3D, material?: Material)
@ -228,13 +228,15 @@ export class ArcDimension extends Dimension
this._StartAngle = file.Read();
this._EndAngle = file.Read();
this._TextString = file.Read();
this._TextSize = file.Read();
if (ver > 1) this._FractionDigits = file.Read();
if (ver < 3) this.TextSize = file.Read();
if (ver > 1 && ver < 3) this.FractionDigits = file.Read();
if (ver > 2) this.ReadDimStyle(file);
}
//对象将自身数据写入到文件.
WriteFile(file: CADFiler)
{
file.Write(2);
file.Write(3);
super.WriteFile(file);
file.Write(this._Center.toArray());
file.Write(this._Radius);
@ -243,8 +245,8 @@ export class ArcDimension extends Dimension
file.Write(this._StartAngle);
file.Write(this._EndAngle);
file.Write(this._TextString);
file.Write(this._TextSize);
file.Write(this._FractionDigits);
this.WriteDimStyle(file);
}
//#endregion
}

@ -1,6 +1,10 @@
import { HostApplicationServices } from "../../ApplicationServices/HostApplicationServices";
import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler";
import { DimStyleKeyCode } from "../DimStyle/DimstyleKeyCodeEnum";
import { DimStyleRecord } from "../DimStyle/DimStyleRecord";
import { Entity } from "../Entity/Entity";
import { ObjectId } from "../ObjectId";
import { Text } from "../Text/Text";
@Factory
@ -8,12 +12,79 @@ export abstract class Dimension extends Entity
{
OnlyRenderType = true;
protected _TextString: string;
protected _TextSize: number = HostApplicationServices.dimTextHeight;
protected _Text = new Text(undefined, undefined, "yahei");
protected _FractionDigits: number = HostApplicationServices.fractionDigitsType;
//避免标注实体使用材质
get Material() { return this._MaterialId; }
set Material(materialId: ObjectId) { }
//#region 标注样式
protected _DimStyle: ObjectId;//标注样式
protected _DimStyleOverride: Map<DimStyleKeyCode, any> = new Map;//标注样式替代
//获取覆盖的标注样式(来自Key)
GetDimStyleOverrideValue(key: DimStyleKeyCode): any { return this._DimStyleOverride.get(key); }
//设置覆盖的标注样式
SetDimStyleOverrideValue(key: DimStyleKeyCode, value: any)
{
if (this.GetDimStyleOverrideValue(key) === value) return;
this.WriteAllObjectRecord();
let oldV = this.GetDimStyleValue(key);
this._DimStyleOverride.set(key, value);
if (oldV !== value)
this.Update();
}
DeleteDimStyleOverrideValue(key: DimStyleKeyCode)
{
if (!this._DimStyleOverride.has(key)) return;
this.WriteAllObjectRecord();
this._DimStyleOverride.delete(key);
this.Update();
}
ClearDimStyleOverride()
{
if (this._DimStyleOverride.size === 0) return;
this.WriteAllObjectRecord();
this._DimStyleOverride.clear();
this.Update();
}
//获取当前的标注样式值
GetDimStyleValue(key: DimStyleKeyCode)
{
let value = this.GetDimStyleOverrideValue(key);
if (value !== undefined) return value;
if (this._DimStyle?.Object)
return this._DimStyle.Object[DimStyleKeyCode[key]];
if (HostApplicationServices.CurrentDimStyle && HostApplicationServices.CurrentDimStyle.Object instanceof DimStyleRecord)
return HostApplicationServices.CurrentDimStyle.Object[DimStyleKeyCode[key]];
}
get DimStyle() { return this._DimStyle; }
/**设置标注样式 */
set DimStyle(styleId: ObjectId)
{
if (styleId === this._DimStyle) return;
this.WriteAllObjectRecord();
this._DimStyle = styleId;
this.Update();
}
//#endregion
set TextString(txt: string)
{
let str = this.GetString();
let str = this.GetPrimitiveString();
let tstr = this._TextString ? this._TextString.replace("<>", str) : str;
if (txt !== tstr)
{
@ -28,38 +99,50 @@ export abstract class Dimension extends Entity
get TextString()
{
return this._TextString ? this._TextString.replace("<>", this.GetString()) : this.GetString();
return this._TextString ? this._TextString.replace("<>", this.GetPrimitiveString()) : this.GetPrimitiveString();
}
/**计算文字盒子占用的宽度 */
get TextBoxWidth()
{
return this.TextString.length * Math.abs(this.TextSize / 2) * 1.35;
}
get TextSize() { return this.GetDimStyleValue(DimStyleKeyCode.DIMTXT); }
set TextSize(size: number)
{
if (this._Text.Height !== size)
{
this.WriteAllObjectRecord();
this._TextSize = size;
this.Update();
}
this.SetDimStyleOverrideValue(DimStyleKeyCode.DIMTXT, size);
}
get TextSize()
get FractionDigits() { return this.GetDimStyleValue(DimStyleKeyCode.DIMALTD); }
set FractionDigits(length: number)
{
return this._TextSize;
this.SetDimStyleOverrideValue(DimStyleKeyCode.DIMALTD, length);
}
set FractionDigits(length: number)
/**未被修改过的 原始显示字符串,供内部使用 实际文字需要使用.TextString */
protected abstract GetPrimitiveString(): string;
protected ReadDimStyle(file: CADFiler)
{
if (this._FractionDigits !== length)
this._DimStyleOverride.clear();
let size = file.Read();
for (let i = 0; i < size; i++)
{
this.WriteAllObjectRecord();
this._FractionDigits = length;
this.Update();
let k = file.Read();
let v = file.Read();
this._DimStyleOverride.set(k, v);
}
}
get FractionDigits()
protected WriteDimStyle(file: CADFiler)
{
return this._FractionDigits;
file.Write(this._DimStyleOverride.size);
for (let [k, v] of this._DimStyleOverride)
{
file.Write(k);
file.Write(v);
}
}
protected abstract GetString(): string;
}

@ -7,16 +7,17 @@ import { AlignedDimension } from "./AlignedDimension";
enum DimDir
{
/**
*
*/
/**水平 */
H = 0,
/**
*
*/
/**垂直 */
V = 1
}
/**
* 线 http://docs.autodesk.com/ACD/2011/ENU/filesDXF/WS1a9193826455f5ff18cb41610ec0a2e719-7a23.htm
* Autodesk线,AcDbRotatedDimension,50() 52()
* ArmPt
*/
@Factory
export class LinearDimension extends AlignedDimension
{
@ -26,9 +27,11 @@ export class LinearDimension extends AlignedDimension
{
return super.TextPosition;
}
//在设置TextPos时,同时会影响标注的方向(H水平 V竖直) (严格来说,这个点应该是标注线的位置,因为文字位置总是总中心.)
set TextPosition(p: Vector3)
{
p = p.clone().applyMatrix4(this.OCSInv);
p = p.clone().applyMatrix4(this.OCSInv).setZ(0);
let bit = 0;//x 1 y 2
if (isBetweenNums(this._FootP1.x, this._FootP2.x, p.x))
bit |= 1;
@ -39,31 +42,35 @@ export class LinearDimension extends AlignedDimension
this._DimDir = DimDir.H;
else if (bit === 2)
this._DimDir = DimDir.V;
//else 叠加态(在中间时,不做变更)
if (this._DimDir === DimDir.H)
{
this._ArmP1.copy(this._FootP1).setY(p.y);
this._ArmP2.copy(this._FootP2).setY(p.y);
this._ArmP1.copy(this._FootP1).setY(p.y).setZ(0);
this._ArmP2.copy(this._FootP2).setY(p.y).setZ(0);
}
else
{
this._ArmP1.copy(this._FootP1).setX(p.x);
this._ArmP2.copy(this._FootP2).setX(p.x);
this._ArmP1.copy(this._FootP1).setX(p.x).setZ(0);
this._ArmP2.copy(this._FootP2).setX(p.x).setZ(0);
}
this.Update();
}
ChangeFootPt()
override OnChangeFootPt()
{
let l = new Line(this._ArmP1, this._ArmP2);
//这个代码有个bug,当footPt在肩线(标注线)上时,这个无法更新,更稳妥似乎应该用 if(!equalv2())???
if (!equaln(this._FootP1.x, this._ArmP1.x) && !equaln(this._FootP1.y, this._ArmP1.y))
{
let cp1 = l.GetClosestPointTo(this._FootP1, true);
this._ArmP1.copy(cp1);
this._ArmP1.copy(cp1).setZ(0);
}
if (!equaln(this._FootP2.x, this._ArmP2.x) && !equaln(this._FootP2.y, this._ArmP2.y))
{
let cp2 = l.GetClosestPointTo(this._FootP2, true);
this._ArmP2.copy(cp2);
this._ArmP2.copy(cp2).setZ(0);
}
}
}

@ -14,7 +14,6 @@ import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler";
import { Circle } from "../Entity/Circle";
import { Line } from "../Entity/Line";
import { ObjectId } from "../ObjectId";
import { Dimension } from "./Dimension";
import { GetDimLineMaterial } from "./GetDimLineMaterial";
@ -43,23 +42,23 @@ export class RadiusDimension extends Dimension
return this._Text;
}
protected GetString(): string
protected GetPrimitiveString(): string
{
return FixedNotZero(this._Center.distanceTo(this._DiameterOrRadiusPoint), this._FractionDigits);
return FixedNotZero(this._Center.distanceTo(this._DiameterOrRadiusPoint), this.FractionDigits);
}
set Material(materialId: ObjectId) { }
get Center()
{
return this._Center.clone().applyMatrix4(this._Matrix);
}
set Center(v: Vector3)
{
this.WriteAllObjectRecord();
this._Center.copy(v).applyMatrix4(this.OCSInv);
this.Update();
}
get DiameterOrRadiusPoint()
{
return this._DiameterOrRadiusPoint.clone().applyMatrix4(this._Matrix);
@ -189,7 +188,7 @@ export class RadiusDimension extends Dimension
this._Text.TextString = this.TextString;
this._Text.Position = this._TextPoint;
this._Text.TextRotation = angleAndX(armV);
this._Text.Height = this._TextSize;
this._Text.Height = this.TextSize;
this._Text.DeferUpdate();
this._Text.AutoUpdate = true;
@ -280,18 +279,20 @@ export class RadiusDimension extends Dimension
this._DiameterOrRadiusPoint.fromArray(file.Read());
this._TextPoint.fromArray(file.Read());
if (ver > 1) this._TextString = file.Read();
if (ver > 2) this._TextSize = file.Read();
if (ver > 3) this._FractionDigits = file.Read();
if (ver > 2 && ver < 5) this.TextSize = file.Read();
if (ver > 3 && ver < 5) this.FractionDigits = file.Read();
if (ver > 4) this.ReadDimStyle(file);
}
WriteFile(file: CADFiler)
{
super.WriteFile(file);
file.Write(4);
file.Write(5);
file.Write(this._Center.toArray());
file.Write(this._DiameterOrRadiusPoint.toArray());
file.Write(this._TextPoint.toArray());
file.Write(this._TextString);
file.Write(this._TextSize);
file.Write(this._FractionDigits);
this.WriteDimStyle(file);
}
}

@ -1,4 +1,4 @@
import { Geometry, Line as TLine, LineSegments, Matrix3, Matrix4, Mesh, Object3D, ShapeGeometry, UVGenerator, Vector3 } from 'three';
import { Euler, Geometry, Line as TLine, LineSegments, Matrix3, Matrix4, Mesh, Object3D, ShapeGeometry, UVGenerator, Vector3 } from 'three';
import { Board2Regions } from '../../Add-on/BoardEditor/Board2Regions';
import { DeserializationBoard2DModeingData, DeserializationBoard3DModeingData, deserializationBoardData, SerializeBoard2DModeingData, SerializeBoard3DModeingData, serializeBoardData } from '../../Add-on/BoardEditor/SerializeBoardData';
import { CyHoleInBoard, ParseBoardRectHoleType, SetBrHighHoleTypeFromRectHoleType, TempRectHoleOption } from '../../Add-on/DrawDrilling/HoleUtils';
@ -919,10 +919,28 @@ export class Board extends ExtrudeSolid
this._SpaceOCS.copy(spcocs);
this.Update();
}
/**实际上这个值可能被改变,应该适当的去校验它(仅在重新设计模块时,这个值会被改变!) */
get Rotation()
{
let roMtx = this.RotateMat;
let roMtxInv = roMtx.getInverse(roMtx);
let csInSpace = this.SpaceOCSInv.multiply(this.OCSNoClone);//逆到模块坐标系
csInSpace.multiply(roMtxInv);//(正确)
csInSpace.setPosition(0, 0, 0);
let euRoMtx = new Matrix4().makeRotationFromEuler(new Euler(this._Rotation.x, this._Rotation.y, this._Rotation.z, "ZYX"));
if (euRoMtx.elements.every((v, i) => equaln(v, csInSpace.elements[i])))
return this._Rotation;
else
{
let eu = new Euler(0, 0, 0, "ZYX").setFromRotationMatrix(csInSpace);
return eu;
}
}
protected ApplyMirrorMatrix(m: Matrix4)
{
if (!this.Id)

@ -97,10 +97,7 @@ export class Entity extends CADObject
this.UpdateDrawObjectMaterial(type, obj);
}
get Material()
{
return this._MaterialId;
}
get Material() { return this._MaterialId; }
set ColorIndex(color: number)
{

@ -6,9 +6,9 @@ import { EntityUpdateWrap } from "../../../../Common/EntityUpdateWrap";
import { ObjectSnapMode } from "../../../../Editor/ObjectSnapMode";
import { Box3Ext } from "../../../../Geometry/Box";
import { BufferGeometryUtils } from "../../../../Geometry/BufferGeometryUtils";
import { SubtractRange, Tape } from "../../../../Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";
import { equaln, equalv3, midPoint, MoveMatrix, ZAxis, ZeroVec } from "../../../../Geometry/GeUtils";
import { RenderType } from "../../../../GraphicsSystem/RenderType";
import { SubtractRange, Tape } from "../../../../ueapi";
import { Factory } from "../../../CADFactory";
import { CADFiler } from "../../../CADFiler";
import { Curve } from "../../../Entity/Curve";

@ -1,8 +1,8 @@
import { EntitysUpdateWrap } from "../../../Common/EntityUpdateWrap";
import { Route } from "../../../Geometry/CurveMap";
import { ContourTreeNode } from "../../../Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2";
import { RegionParse } from "../../../Geometry/RegionParse";
import { Polyline2Points } from "../../../Nest/Converter/Curves2Points";
import { ContourTreeNode } from "../../../ueapi";
import { Contour } from "../../Contour";
import { Database } from "../../Database";
import { Curve } from "../../Entity/Curve";

@ -51,6 +51,12 @@ export class SymbolTable extends CADObject
}
}
override Destroy(): void
{
super.Destroy();
this.Symbols.clear();
}
GetAt(name: string): SymbolTableRecord | undefined
{
return this.Symbols.get(name);

@ -1,9 +1,9 @@
import { CADObject } from "./CADObject";
import { Status } from "../Common/Status";
import { CADFiler } from "./CADFiler";
import { CADObject } from "./CADObject";
import { SymbolTable } from "./SymbolTable";
import { Status } from "../Common/Status";
export class SymbolTableRecord extends CADObject
export abstract class SymbolTableRecord extends CADObject
{
protected name: string = "";
get Name()

@ -1,6 +1,5 @@
import { Geometry, MathUtils, Matrix4, Mesh, Object3D, ShapeGeometry, Vector3 } from 'three';
import { Geometry, Matrix4, Mesh, Object3D, ShapeGeometry, Vector3 } from 'three';
import { ColorMaterial } from '../../Common/ColorPalette';
import { setRotationOnAxis } from '../../Common/Matrix4Utils';
import { UpdateDraw } from '../../Common/Status';
import { Box3Ext } from '../../Geometry/Box';
import { GetBox, MoveMatrix } from '../../Geometry/GeUtils';
@ -44,7 +43,6 @@ export class Text extends Entity
{
super();
pos && this._Matrix.setPosition(pos);
this._TextRotation && setRotationOnAxis(this._Matrix, this.Normal, MathUtils.degToRad(this._TextRotation));
}
get TextRotation()
{

@ -1,5 +1,4 @@
import { Geometry, Mesh, MeshBasicMaterial, Object3D, Scene, ShapeGeometry, Vector3, WebGLRenderer, WebGLRenderTarget } from "three";
import { CADFiler } from "../../api";
import { app } from "../../ApplicationServices/Application";
import { ColorMaterial } from "../../Common/ColorPalette";
import { clamp } from "../../Common/Utils";
@ -7,6 +6,7 @@ import { GetBox } from "../../Geometry/GeUtils";
import { CameraUpdate } from "../../GraphicsSystem/CameraUpdate";
import { RenderType } from "../../GraphicsSystem/RenderType";
import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler";
import { Entity } from "../Entity/Entity";
import { Polyline } from "../Entity/Polyline";
import { ObjectId } from "../ObjectId";

@ -258,7 +258,7 @@ export class BoardMoveTool
{
let dim = new AlignedDimension();
dim.TextSize = 20;
dim.LeadOutVisible = false;
dim.LeadVisible = false;
this._DrawDims.push(dim);
app.Viewer.PreViewer.Scene.add(dim.DrawObject);
}

@ -5,7 +5,7 @@ import { IUpdateBoardInfosOption } from "../UI/Components/Board/UpdateBoardInfoi
import { EMetalsType, ICompHardwareOption, ICylMetalsOption, IExtMetalsOption, IToplineOption } from "../UI/Components/RightPanel/RightPanelInterface";
import { IKuGangDrawOption } from "../UI/Components/Template/TemplateInterface";
import { ECompareType, IBoardFindOption } from "../UI/Store/BoardFindInterface";
import { BehindBoardOption, BehindHeightPositon, BoardProcessOption, BoardType, BrRelativePos, ClosingStripOption, CommonPanelConfigOption, ComposingType, CurtailType, FaceDirection, IBatchModifyPanelOption, IBoardBatchCurtailOption, KJLImportConfigOption, LayerBoardOption, LayerNailOption, LinesType, ModifyTextsConfigOption, PointLightOption, RadioType, RectAreaLightOption, RightPlaneLightOption, SideBoardOption, SingleBoardOption, SpotLightOption, StripType, TBBoardOption, VerticalBoardOption, Viewport2ConfigOption, Viewport3ConfigOption, Viewport4ConfigOption, ViewportConfigOption } from "../UI/Store/BoardInterface";
import { BehindBoardOption, BehindHeightPositon, BoardProcessOption, BoardType, BrRelativePos, ClosingStripOption, CommonPanelConfigOption, ComposingType, CurtailType, FaceDirection, IAutoDimBrsOption, IBatchModifyPanelOption, IBoardBatchCurtailOption, KJLImportConfigOption, LayerBoardOption, LayerNailOption, LinesType, ModifyTextsConfigOption, PointLightOption, RadioType, RectAreaLightOption, RightPlaneLightOption, SideBoardOption, SingleBoardOption, SpotLightOption, StripType, TBBoardOption, VerticalBoardOption, Viewport2ConfigOption, Viewport3ConfigOption, Viewport4ConfigOption, ViewportConfigOption } from "../UI/Store/BoardInterface";
import { DoorPosType, HandleHorPos, HandleVePos, IDoorConfigOption, IDrawerConfigOption, IHingeConfigOption } from "../UI/Store/DoorInterface";
import { IHSOption } from "../UI/Store/HSInterface";
import { ELatticeArrayType, ILatticeOption } from "../UI/Store/LatticeInterface";
@ -863,3 +863,19 @@ export const DefaultCommonPanelOption: CommonPanelConfigOption = {
orderType: EOrderType.ByUpdate,
};
Object.freeze(DefaultCommonPanelOption);
export const DefaultAutoDimBrsOption: IAutoDimBrsOption = {
total: true,
out: true,
inW: false,
inH: false,
noRepeat: false,
noSmSize: false,
noAppointSize: false,
noInSize: false,
noShowMinSize: 20,
noShowMinInSize: 300,
noShowAppointSizes: "",
useParseGroups: "0"
};
Object.freeze(DefaultAutoDimBrsOption);

@ -36,7 +36,7 @@ export interface IUCSGridConfig extends IBaseOption
export class UserConfig implements IConfigStore
{
private readonly _version = 30; //🌟🌟每次更新必须向上添加一次版本号🌟🌟
private readonly _version = 31; //🌟🌟每次更新必须向上添加一次版本号🌟🌟
_renderType: RenderType = RenderType.Wireframe;
@observable maxSize: IMaxSizeProps = {
isShow: false,
@ -112,7 +112,6 @@ export class UserConfig implements IConfigStore
};
@observable autoLines = false;
@observable dimTextHeight = 60;
@observable performanceConfig = {
fakersweep: false,
disablerefcut: false,

@ -1,17 +1,14 @@
import { Matrix2 } from './Matrix2';
let r = new Matrix2();
export const ROTATE_MTX2 = new Matrix2().set(0, -1, 1, 0);
export function RotateUVs(geo: THREE.Geometry)
{
r.set(0, -1,
1, 0);
for (let uvs of geo.faceVertexUvs)
{
for (let uv of uvs)
{
for (let v of uv)
r.applyVector(v);
ROTATE_MTX2.applyVector(v);
}
}
geo.uvsNeedUpdate = true;

@ -15,16 +15,17 @@ import { ISpaceParse } from "./ISpaceParse";
*/
export class SurroundOutlineParse extends ISpaceParse
{
Polylines: Polyline[] = [];
Outlines: Curve[] = [];
Polylines: Polyline[] = [];//完整轮廓(ucs z0)
Outlines: Curve[] = [];//完整轮廓炸开后的线(ucs zMax)
async Parse()
{
let ucsNormal = new Vector3().setFromMatrixColumn(app.Editor.UCSMatrix, 2);
let ucsInv = app.Editor.UCSMatrixInv;
let boardList = this.ParseBoardList();
for (let brs of boardList)
let groups = this.GroupBoards();
for (let brs of groups)
{
let pls: Polyline[] = [];
//板转多段线轮廓
let brPls: Polyline[] = [];
let maxZ = -Infinity;
for (let br of brs)
{
@ -40,9 +41,9 @@ export class SurroundOutlineParse extends ISpaceParse
new Vector3(min.x, max.y, max.z), max
];
//br->ucs
let mtx = new Matrix4().multiplyMatrices(ucsInv, br.OCS);
let mtx = new Matrix4().multiplyMatrices(ucsInv, br.OCSNoClone);
pts.forEach(p => p.applyMatrix4(mtx));
pts.sort((p1, p2) => p1.z - p2.z);
pts.sort((p1, p2) => p1.z - p2.z);//下面4个点 上面4个点
if (isParallelTo(brNormal, ucsNormal))
{
let cu = br.ContourCurve;
@ -50,88 +51,90 @@ export class SurroundOutlineParse extends ISpaceParse
{
let pl = cu.Clone().ApplyMatrix(mtx);
pl.Position = pl.Position.setZ(0);
pls.push(pl);
brPls.push(pl);
}
}
else if (isPerpendicularityTo(brNormal, ucsNormal))
pls.push(getRectFrom4Pts(pts.slice(0, 4)));
brPls.push(getRectFrom4Pts(pts.slice(0, 4)));
else
continue;
maxZ = Math.max(maxZ, arrayLast(pts).z);
}
if (pls.length === 0) return;
let retCus = this.GetOutline(pls);
//变换到最高点
let ucs = app.Editor.UCSMatrix;
let p = new Vector3().setFromMatrixPosition(ucs);
p.add(ucsNormal.clone().multiplyScalar(maxZ));
ucs.setPosition(p);
if (brPls.length === 0) continue;
for (let cu of retCus)
cu.ApplyMatrix(ucs);
this.Outlines.push(...retCus);
}
}
private GetOutline(cus: Curve[])
{
let reg = Region.CreateFromCurves([cus.shift()]);
for (let pl of cus)
//并集轮廓
let reg = Region.CreateFromCurves([brPls.shift()]);
for (let pl of brPls)
{
let plreg = Region.CreateFromCurves([pl]);
if (plreg)
reg.BooleanOper(plreg, BoolOpeartionType.Union);
}
let pls = reg.ShapeManager.ShapeList.map(s => s.Outline.Curve) as Polyline[];
this.Polylines.push(...pls);
let retCus: Curve[] = [];
for (let pl of pls)
let unionPls = reg.ShapeManager.ShapeList.map(s => s.Outline.Curve as Polyline);
for (let pl of unionPls)
this.Polylines.push(pl);
//变换到最高点矩阵
let ucs = app.Editor.UCSMatrix;
let p = new Vector3().setFromMatrixPosition(ucs)
.add(ucsNormal.clone().multiplyScalar(maxZ));
ucs.setPosition(p);
//炸开
for (let pl of unionPls)
{
let cus = pl.Explode().filter(cu => !equaln(cu.Length, 0, 1e-6));
retCus.push(...cus);
for (let cu of pl.Explode())
if (!equaln(cu.Length, 0, 1e-6))
{
cu.ApplyMatrix(ucs);//move max z
this.Outlines.push(cu);
}
}
}
return retCus;
}
private ParseBoardList()
//根据包围盒对板进行分堆
private GroupBoards()
{
let boxMap: Map<Box3, Board> = new Map();
let boxes: Box3[] = [];
let boxMap: Map<Board, Box3> = new Map();
for (let br of this.Boards)
boxMap.set(br, br.GetBoundingBoxInMtx(this.SpaceOCSInv));
let brGroups: (Board[])[] = [];
let brs = this.Boards.concat();
while (brs.length)
{
let box = br.GetBoundingBoxInMtx(this.SpaceOCSInv);
boxes.push(box);
boxMap.set(box, br);
}
let boardList: Board[][] = [];
while (boxes.length > 0)
{
let originBox = boxes.shift();
let brs = [boxMap.get(originBox)];
while (true)
let group = [brs.pop()];
let groupBox = boxMap.get(group[0]).clone();
while (brs.length)
{
let remBoxes = boxes.filter(b =>
let index = brs.findIndex(br =>
{
if (originBox.intersectsBox(b))
let box = boxMap.get(br);
if (box.intersectsBox(groupBox))
{
originBox.union(b);
brs.push(boxMap.get(b));
return false;
}
groupBox.union(box);
group.push(br);
return true;
}
return false;
});
if (remBoxes.length === boxes.length)
if (index !== -1)
{
boardList.push(brs);
break;
brs.splice(index, 1);
continue;
}
else
boxes = remBoxes;
break;
}
brGroups.push(group);
}
return boardList;
return brGroups;
}
}

@ -49,11 +49,15 @@ export class Viewer
//前置渲染
PreViewer: PreViewer;
/**使用后期渲染器 */
UsePass = false;
/**后期渲染器 */
Composer: EffectComposer;
_AAType: AAType = AAType.FXAA;
RenderPass: RenderPass;
OutlinePass: OutlinePass;
Composer: EffectComposer;
private _SMAAPass: SMAAPass;
private _Scene: Scene = new Scene;

@ -1,7 +1,7 @@
import { MathUtils } from "three";
import { Arc } from "../api";
import { arrayLast } from "../Common/ArrayExt";
import { CADObject } from "../DatabaseServices/CADObject";
import { Arc } from "../DatabaseServices/Entity/Arc";
import { Curve } from "../DatabaseServices/Entity/Curve";
import { RoomHolePolyline } from "../DatabaseServices/Room/Entity/Wall/Hole/RoomHolePolyline";
import { RoomWallArc } from "../DatabaseServices/Room/Entity/Wall/RoomWallArc";

@ -1,89 +1,260 @@
import { Button, Card, Checkbox, H5, Intent } from '@blueprintjs/core';
import React, { Component } from 'react';
import { Button, Checkbox, Classes, Intent, Position, Radio, RadioGroup, Tooltip } from '@blueprintjs/core';
import { autorun, observable } from 'mobx';
import { observer } from 'mobx-react';
import React from 'react';
import { begin } from 'xaop';
import { AutoDimBrsStore } from '../../Add-on/DrawDim/AutoDimBrsStore';
import { EDimType } from '../../Add-on/DrawDim/AutoDimBrsTool';
import { app } from '../../ApplicationServices/Application';
import { safeEval } from '../../Common/eval';
import { KeyBoard } from '../../Common/KeyEnum';
import { GetCompoentObjectIdString } from './ComponentObjectId';
import { BoardModalType } from './Board/BoardModalType';
import { UserConfig } from './Board/UserConfig';
import { ModalHeader } from './Modal/ModalContainer';
import { ModalState } from './Modal/ModalInterface';
interface IAutoDimBoardPanel
{
dimType: EDimType;
}
@observer
export class AutoDimBoardPanel extends React.Component<{ store: AutoDimBrsStore; }> {
_Event: Function[] = [];
@observable _StrIllegal = false;
_NoShowMinSizeInput: React.RefObject<HTMLInputElement> = React.createRef();
_NoShowMinInSizeInput: React.RefObject<HTMLInputElement> = React.createRef();
_NoShowAppointDimSizeInput: React.RefObject<HTMLInputElement> = React.createRef();
export default class AutoDimBoardPanel extends Component<IAutoDimBoardPanel, { type: EDimType; }> {
private dimType: EDimType;
private event: Function;
constructor(props)
{
super(props);
this.state = {
type: this.props.dimType
};
this.dimType = this.props.dimType;
}
componentDidMount()
{
this.event = begin(app.Editor.ModalManage, app.Editor.ModalManage.OnKeyDown, (e: KeyboardEvent) =>
this._Event.push(
begin(app.Editor.ModalManage, app.Editor.ModalManage.OnKeyDown, (e: KeyboardEvent) =>
{
if (GetCompoentObjectIdString(AutoDimBoardPanel) !== app.Editor.ModalManage.CurrentModalKey) return;
let el = e.target as HTMLInputElement;
if (e.keyCode === KeyBoard.Enter || e.keyCode === KeyBoard.Space)
{
this.onOk();
//使用左右侧板时,该事件会使 拾取点的动态输入框响应到这个键盘事件.
//导致进入交互时,马上有个空格.
this._OnOk();
e.preventDefault();
}
e.stopPropagation();
return true;
});
})
);
this._Event.push(
autorun(() =>
{
if (this._NoShowAppointDimSizeInput)
this._NoShowAppointDimSizeInput.current.value = this.props.store.m_Option.noShowAppointSizes;
if (this._NoShowMinInSizeInput)
this._NoShowMinInSizeInput.current.value = this.props.store.m_Option.noShowMinInSize.toFixed();
if (this._NoShowMinSizeInput)
this._NoShowMinSizeInput.current.value = this.props.store.m_Option.noShowMinSize.toFixed();
})
);
}
componentWillUnmount()
{
if (this.event)
{
this.event();
this.event = null;
}
for (let f of this._Event) f();
this._Event.length = 0;
}
render()
{
let option = this.props.store.m_Option;
return (
<Card>
<H5></H5>
<Checkbox label="整体标注" data-type={EDimType.Total} defaultChecked={!!(this.dimType & EDimType.Total)} onChange={this.onChange} />
<Checkbox label="柜外标注" data-type={EDimType.Out} defaultChecked={!!(this.dimType & EDimType.Out)} onChange={this.onChange} />
<Checkbox label="柜内宽标注" data-type={EDimType.InW} defaultChecked={!!(this.dimType & EDimType.InW)} onChange={this.onChange} />
<Checkbox label="柜内高标注" data-type={EDimType.InH} defaultChecked={!!(this.dimType & EDimType.InH)} onChange={this.onChange} />
<Checkbox label="过滤重复标注" data-type={EDimType.NoRepeat} defaultChecked={!!(this.dimType & EDimType.NoRepeat)} onChange={this.onChange} />
<Checkbox label="过滤小尺寸标注" data-type={EDimType.NoSmSize} defaultChecked={!!(this.dimType & EDimType.NoSmSize)} onChange={this.onChange} />
<div>
<Button text="确定" intent={Intent.SUCCESS} onClick={this.onOk} />
<Button text="取消" intent={Intent.DANGER} onClick={this.onCancel} />
<div id='AutoDimBoardConfig' className={Classes.DIALOG_CONTAINER}>
<div className={Classes.DIALOG + " autoDimBoardConfig"}>
<ModalHeader
title={"自动标注配置"}
close={this._Cancel}
icon="cog"
/>
<div className={Classes.DIALOG_BODY}>
<RadioGroup
onChange={(e) =>
{
option.useParseGroups = e.currentTarget.value;
}}
selectedValue={option.useParseGroups}
className='dimGroup'
>
<Radio label="分堆(多组标注)" value="0" />
<Radio label="不分堆(单组标注)" value="1" />
</RadioGroup>
<div className='dimGroup'>
<Checkbox label="整体标注" checked={option.total} onChange={() => this._OnChange(EDimType.Total)} />
<Checkbox label="柜内宽标注" checked={option.inW} onChange={() => this._OnChange(EDimType.InW)} />
</div>
</Card>
);
<div className='dimGroup'>
<Checkbox label="柜外标注" checked={option.out} onChange={() => this._OnChange(EDimType.Out)} />
<Checkbox label="柜内高标注" checked={option.inH} onChange={() => this._OnChange(EDimType.InH)} />
</div>
{/* <Checkbox label="过滤重复标注" data-type={EDimType.NoRepeat} defaultChecked={!!(this.dimType & EDimType.NoRepeat)} onChange={this.onChange} /> */}
<div className='dimInputGroup'>
<Checkbox label="过滤小尺寸标注" checked={option.noSmSize} onChange={() => this._OnChange(EDimType.NoSmSize)} />
<input className="bp3-input br-process-input"
ref={this._NoShowMinSizeInput}
defaultValue={option.noShowMinSize}
min={1}
style={{ width: 50, height: 28 }}
onKeyDown={(e) =>
{
switch (e.keyCode)
{
case KeyBoard.Escape:
case KeyBoard.Space:
case KeyBoard.Enter:
e.currentTarget.blur();
e.stopPropagation();
break;
default:
break;
}
}}
onBlur={(e) =>
{
let val = safeEval(e.target.value);
if (!isNaN(val))
option.noShowMinSize = parseFloat(e.currentTarget.value);
else
e.target.value = option.noShowMinSize.toFixed();
}}
/>
</div>
<div className='dimInputGroup'>
<Checkbox label="过滤柜内空间标注" checked={option.noInSize} onChange={() => this._OnChange(EDimType.NoInSize)} />
<input className="bp3-input br-process-input"
ref={this._NoShowMinInSizeInput}
defaultValue={option.noShowMinInSize}
min={1}
style={{ width: 50, height: 28 }}
onKeyDown={(e) =>
{
switch (e.keyCode)
{
case KeyBoard.Escape:
case KeyBoard.Space:
case KeyBoard.Enter:
e.currentTarget.blur();
e.stopPropagation();
break;
default:
break;
}
}}
onBlur={(e) =>
{
let val = safeEval(e.target.value);
if (!isNaN(val) && val > 0)
option.noShowMinInSize = parseFloat(e.currentTarget.value);
else
e.target.value = option.noShowMinInSize.toFixed();
}}
/>
</div>
<div className='dimInputGroup'>
<Checkbox label="过滤指定数值标注" checked={option.noAppointSize} onChange={() => this._OnChange(EDimType.NoAppointSize)} />
<Tooltip
content={"请输入大于0的数字! 多个数字可以用 ' | ' 或 逗号 或 空格 相隔!"}
position={Position.TOP}
intent={Intent.WARNING}
isOpen={this._StrIllegal}
>
<Tooltip content="多个数字可以用 ' | ' 或 逗号 或 空格 相隔">
<input className="bp3-input br-process-input"
type={"text"}
ref={this._NoShowAppointDimSizeInput}
defaultValue={option.noShowAppointSizes}
style={{ height: 28 }}
onKeyDown={(e) =>
{
switch (e.keyCode)
{
case KeyBoard.Escape:
case KeyBoard.Enter:
e.currentTarget.blur();
e.stopPropagation();
break;
case KeyBoard.Space:
e.stopPropagation();
break;
default:
break;
}
private onChange = (e: React.ChangeEvent<HTMLInputElement>) =>
}}
onChange={(e) => { this._CheckStr(e); }}
onKeyUp={(e) => { e.currentTarget.value = e.currentTarget.value.replaceAll(//g, ','); }}
onBlur={(e) =>
{
let target = e.target;
let type = parseInt(target.getAttribute("data-type"));
if (target.checked)
if (this._StrIllegal)
{
this.dimType |= type;
e.currentTarget.value = option.noShowAppointSizes;
this._StrIllegal = false;
}
else
{
this.dimType &= (~type);
if (e.currentTarget.value === '')
{
option.noShowAppointSizes = '';
return;
}
//数字简化 0.100 => 0.1
let strArray = [];
let strArray2 = [];
let strArray3 = [];
for (let s1 of e.currentTarget.value.split(','))
{
strArray2 = [];
for (let s2 of s1.split(' '))
{
strArray3 = [];
for (let s3 of s2.split('|'))
{
strArray3.push(safeEval(s3));
}
strArray2.push(strArray3.join('|'));
}
strArray.push(strArray2.join(' '));
}
e.currentTarget.value = strArray.join(',');
option.noShowAppointSizes = e.currentTarget.value;
}
}}
/>
</Tooltip>
</Tooltip>
</div>
</div>
<div className={Classes.DIALOG_FOOTER}>
<UserConfig type={BoardModalType.AutoDimBrs} store={this.props.store} />
<Button text="确定" intent={Intent.SUCCESS} onClick={this._OnOk} />
<Button text="取消" intent={Intent.DANGER} onClick={this._Cancel} />
</div>
</div>
</div>
);
}
_CheckStr = (e: React.ChangeEvent<HTMLInputElement>) =>
{
if (e.currentTarget.value === '') return;
let str = e.currentTarget.value.replaceAll(//g, ',');
//支持 ',' '|' '空格'
this._StrIllegal = !str.split(',').every(str1 => str1.split('|').every(str2 => str2.split(' ').every(str3 => { return !isNaN(safeEval(str3)) && safeEval(str3) > 0; })));
};
private onOk = () =>
_OnChange = (key: string) =>
{
app.Editor.ModalManage.DestoryAndExec({ Status: ModalState.Ok, Data: { type: this.dimType } });
this.props.store.m_Option[key] = !this.props.store.m_Option[key];
};
private onCancel = () =>
_OnOk = () =>
{
app.Editor.ModalManage.DestoryAndExec({ Status: ModalState.Ok, });
};
_Cancel = () =>
{
app.Editor.ModalManage.Destory();
};

@ -1,12 +1,12 @@
import { BreadcrumbProps, Button, Intent, Toaster } from "@blueprintjs/core";
import { observable } from "mobx";
import React, { createRef, RefObject } from "react";
import { CADFiler } from "../../../api";
import { app } from "../../../ApplicationServices/Application";
import { CommandNames } from "../../../Common/CommandNames";
import { CoolDownTime } from "../../../Common/CoolDownTime";
import { inflateBase64 } from "../../../Common/inflate";
import { IResponseData } from "../../../Common/Request";
import { CADFiler } from "../../../DatabaseServices/CADFiler";
import { FileServer } from "../../../DatabaseServices/FileServer";
import { commandMachine } from "../../../Editor/CommandMachine";
import { CommandState } from "../../../Editor/CommandState";

@ -18,7 +18,6 @@ import { userConfigStore } from "../../../Store/UserConfigStore";
import { BoardModalType } from "../../Board/BoardModalType";
import { GetCompoentObjectIdString } from "../../ComponentObjectId";
import { ChaiDanPanel } from "./ChaiDanModal";
import { DimConfigPanel } from "./DimConfigPanel";
import { DisplayConfigPanel } from "./DisplayConfigPanel";
import { DrawConfigPanel } from "./DrawConfigPanel";
import { FileConfigPanel } from "./FileConfigPanel";
@ -33,7 +32,6 @@ export enum EOptionTabId
Draw = "ht",
ChaiDan = "chaidan",
Perf = "perf",
DimStyle = "dimstyle",
TextStyle = "textstyle",
}
@ -251,7 +249,6 @@ export class ConfigDialog extends React.Component<{ store: ConfigStore; selected
<Tab id={EOptionTabId.Sys} title="系统" panel={<SystemConfigPanel />} />
<Tab id={EOptionTabId.Draw} title="绘图" panel={<DrawConfigPanel store={store} />} />
<Tab id={EOptionTabId.ChaiDan} title="拆单" panel={<ChaiDanPanel />} />
<Tab id={EOptionTabId.DimStyle} title="标注" panel={<DimConfigPanel />} />
<Tab id={EOptionTabId.TextStyle} title="文本" panel={<TextConfigPanel />} />
</Tabs>
</div>

@ -1,130 +0,0 @@
import { Card, Classes, HTMLSelect, Intent, Label, Position, Slider, Tooltip } from "@blueprintjs/core";
import { observable } from "mobx";
import { observer } from "mobx-react";
import * as React from 'react';
import { app } from "../../../../ApplicationServices/Application";
import { safeEval } from "../../../../Common/eval";
import { KeyBoard } from "../../../../Common/KeyEnum";
import { FractionDigitsType } from "../../../../Common/SystemEnum";
import { userConfig } from "../../../../Editor/UserConfig";
const WDCss: React.CSSProperties = {
width: 100
};
const Padding: React.CSSProperties = {
padding: "4px 0",
margin: 0
};
@observer
export class DimConfigPanel extends React.Component<{}>
{
@observable _isPopoverOpen: boolean = false;
@observable _dimTextHeight: number = userConfig.dimTextHeight;
_dimInputEl = React.createRef<HTMLInputElement>();
render()
{
return (
<Card>
<div>
<div style={{ display: "inline-flex", ...Padding }}>
<span style={WDCss}></span>
<div>
<div className="numeric_input">
<Tooltip
content={"仅限1-300间的数字!"}
position={Position.TOP}
intent={Intent.WARNING}
isOpen={this._isPopoverOpen}
>
<input
ref={this._dimInputEl}
defaultValue={this._dimTextHeight}
style={{ width: "80%" }}
onKeyDown={(e) =>
{
if (e.keyCode === KeyBoard.Escape)
{
//@ts-ignore
e.target.blur();
}
else if (e.keyCode === KeyBoard.Enter || e.keyCode === KeyBoard.Space)
{
if (!this._isPopoverOpen)
//@ts-ignore
e.target.blur();
else
//@ts-ignore
e.target.focus();
e.preventDefault();
}
e.stopPropagation();
}}
onFocus={() =>
{
this._dimInputEl.current.setSelectionRange(0, this._dimInputEl.current.value.length);
}}
onBlur={(e) =>
{
let val = safeEval(e.target.value);
if (!isNaN(val))
{
if (val <= 0 || val > 300)
{
e.target.value = userConfig.dimTextHeight.toString();
app.Editor.Prompt('文字尺寸仅限1-300!');
}
else
{
this._dimTextHeight = val;
userConfig.dimTextHeight = this._dimTextHeight;
}
}
else
{
e.target.value = userConfig.dimTextHeight.toString();
app.Editor.Prompt('文字尺寸仅限1-300间的数字!');
}
}}
/>
</Tooltip>
</div>
</div>
</div>
<Slider
min={10}
max={300}
stepSize={1}
labelStepSize={40}
onChange={(value) =>
{
this._dimInputEl.current.value = value.toString();
this._dimTextHeight = value;
userConfig.dimTextHeight = this._dimTextHeight;
}}
value={this._dimTextHeight}
vertical={false}
/>
</div>
<Label className={Classes.INLINE} style={Padding}>
<span style={WDCss}></span>
<HTMLSelect
options={
[
{ label: "0", value: FractionDigitsType.zero },
{ label: "1", value: FractionDigitsType.one },
{ label: "2", value: FractionDigitsType.two },
{ label: "3", value: FractionDigitsType.three },
{ label: "4", value: FractionDigitsType.four },
{ label: "5", value: FractionDigitsType.five },
]
}
value={userConfig.fractionDigitsType}
onChange={e => userConfig.fractionDigitsType = parseInt(e.target.value)}
/>
</Label>
</Card >
);
}
}

@ -1,5 +1,5 @@
import { IBaseOption } from "../../Store/BoardInterface";
import { EBoardKeyList } from "../../../Common/BoardKeyList";
import { IBaseOption } from "../../Store/BoardInterface";
export interface IHardwareOption extends IBaseOption
{
@ -42,7 +42,7 @@ export enum EMetalsType
export interface ICompHardwareOption extends IHardwareOption
{
type: EMetalsType;
isSplite: boolean;
isSplite: boolean;//拆解
isSplitePrice: boolean;
color: string;
[EBoardKeyList.Mat]: string;

@ -3,12 +3,12 @@ import { observable } from "mobx";
import { observer } from "mobx-react";
import pako from "pako";
import React from "react";
import { CADFiler } from "../../../api";
import { app } from "../../../ApplicationServices/Application";
import { FileSystem } from '../../../Common/FileSystem';
import { TemplateUrls } from "../../../Common/HostUrl";
import { PostJson } from "../../../Common/Request";
import { StoreageKeys } from "../../../Common/StoreageKeys";
import { CADFiler } from "../../../DatabaseServices/CADFiler";
import { FileServer } from "../../../DatabaseServices/FileServer";
import { TopPanelStore } from "../../Store/TopPanelStore";
import { AppToaster } from "../Toaster";

@ -4,7 +4,9 @@ import { app } from "../../../ApplicationServices/Application";
import { EBoardKeyList } from "../../../Common/BoardKeyList";
import { TransformVector } from "../../../Common/Matrix4Utils";
import { Sleep } from "../../../Common/Sleep";
import { DuplicateRecordCloning } from "../../../Common/Status";
import { GetEntity } from "../../../Common/Utils";
import { Board } from "../../../DatabaseServices/Entity/Board";
import { Entity } from "../../../DatabaseServices/Entity/Entity";
import { HardwareCompositeEntity } from "../../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { HardwareTopline } from "../../../DatabaseServices/Hardware/HardwareTopline";
@ -17,7 +19,6 @@ import { PromptStatus } from "../../../Editor/PromptResult";
import { ParsePlaceEntitys } from "../../../Editor/TranstrolControl/ParsePlaceEntitys";
import { ParsePlacePos, ParsePlacePosWithTemplate, ParsePlacePosWithTemplate2 } from "../../../Editor/TranstrolControl/ParsePlacePos";
import { equaln, equalv3, ZeroVec } from "../../../Geometry/GeUtils";
import { Board, DuplicateRecordCloning } from "../../../ueapi";
import { DownPanelStore } from "../../Store/DownPanelStore";
import { IGetRoomInfo } from "./GetRoomCabName";

@ -6,6 +6,7 @@ import { app } from '../../../ApplicationServices/Application';
import { safeEval } from '../../../Common/eval';
import { IsMeshMaterialEntity } from '../../../Common/IsMeshMaterialEntity';
import { KeyBoard } from '../../../Common/KeyEnum';
import { Board } from '../../../DatabaseServices/Entity/Board';
import { Curve } from '../../../DatabaseServices/Entity/Curve';
import { Entity } from '../../../DatabaseServices/Entity/Entity';
import { HardwareCompositeEntity } from '../../../DatabaseServices/Hardware/HardwareCompositeEntity';
@ -20,7 +21,6 @@ import { CommandWrap } from '../../../Editor/CommandMachine';
import { JigUtils } from '../../../Editor/JigUtils';
import { PromptStatus } from '../../../Editor/PromptResult';
import { GetBoardHighSeal, GetBoardSealingCurves } from '../../../GraphicsSystem/CalcEdgeSealing';
import { Board } from '../../../ueapi';
import { ITemplateParam } from "../../Store/RightPanelStore/ITemplateParam";
import { RightPanelStore } from '../../Store/RightPanelStore/RightPanelStore';
import { TempalteEditorStore } from '../../Store/TemplateEditorStore';

@ -1,9 +1,10 @@
import { app } from "../../../ApplicationServices/Application";
import { EBoardKeyList } from "../../../Common/BoardKeyList";
import { DuplicateRecordCloning } from "../../../Common/Status";
import { Board } from "../../../DatabaseServices/Entity/Board";
import { HardwareCompositeEntity } from "../../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { PositioningHandleSpace } from "../../../DatabaseServices/Template/Positioning/PositioningHandleSpace";
import { TemplateRecord } from "../../../DatabaseServices/Template/TemplateRecord";
import { Board, DuplicateRecordCloning } from "../../../ueapi";
import { BoardOpenDir } from "../../Store/BoardInterface";
import { DoorStore } from "../../Store/DoorDrawerStore/DoorStore";
import { HandleHorPos, HandleVePos } from "../../Store/DoorInterface";

@ -0,0 +1,179 @@
import { Intent, Position, Slider, Tooltip } from "@blueprintjs/core";
import { observable } from "mobx";
import { observer } from "mobx-react";
import React from "react";
import { app } from "../../../ApplicationServices/Application";
import { safeEval } from "../../../Common/eval";
import { KeyBoard } from "../../../Common/KeyEnum";
import { FixedNotZero } from "../../../Common/Utils";
import { AlignedDimension } from "../../../DatabaseServices/Dimension/AlignedDimension";
import { Dimension } from "../../../DatabaseServices/Dimension/Dimension";
import { DimStyleKeyCode } from "../../../DatabaseServices/DimStyle/DimstyleKeyCodeEnum";
import { commandMachine, CommandWrap } from "../../../Editor/CommandMachine";
import { CommandState } from "../../../Editor/CommandState";
import { AppToaster } from "../Toaster";
import { DimParamsList } from "./Properties_Dim";
interface DimParamsPanelProps
{
dims: Dimension[];
dimParam: [string, string];
changeFunction: (dim: AlignedDimension, length: number, keys: string[]) => void;
}
@observer
export class DimParamsPanel extends React.Component<DimParamsPanelProps, {}>
{
@observable _ParamValue: number = 0;
@observable _MinValue: number = 0;
@observable _MaxValue: number = 0;
@observable _IsPopoverOpen: boolean = false;
@observable _StepSize: number = 1;
_InputRef: React.RefObject<HTMLInputElement> = React.createRef<HTMLInputElement>();;
_SilderRef: React.RefObject<Slider> = React.createRef<Slider>();;
constructor(props)
{
super(props);
let dim = (this.props.dims[0] as AlignedDimension);
switch (this.props.dimParam[0])
{
case DimParamsList.FootLineLength:
this._ParamValue = dim.GetDimStyleValue(DimStyleKeyCode.DIMFXL);
this._MaxValue = 500;
this._StepSize = 1;
break;
case DimParamsList.ArrowSize:
this._ParamValue = dim.GetDimStyleValue(DimStyleKeyCode.DIMASZ);
this._MaxValue = 20;
this._StepSize = 1;
break;
}
}
changeElValue(value: number)
{
this._ParamValue = value;
this._InputRef.current.value = FixedNotZero(value, 1);
}
render()
{
return (
<div className="paramPanel">
<div className="input_group">
<span>{this.props.dimParam[1]}: </span>
<div className="numeric_input" >
<Tooltip
content={"仅限" + this._MinValue + "-" + this._MaxValue + "间的数字!"}
position={Position.TOP}
intent={Intent.WARNING}
isOpen={this._IsPopoverOpen}
>
<input
ref={this._InputRef}
defaultValue={this._ParamValue}
style={{ width: "100%" }}
onChange={(e) =>
{
let val = safeEval(e.target.value);
if (!isNaN(val))
{
if (val < this._MinValue || val > this._MaxValue)
this._IsPopoverOpen = true;
else
this._IsPopoverOpen = false;
}
else
this._IsPopoverOpen = true;
}}
onKeyDown={(e) =>
{
if (e.keyCode === KeyBoard.Escape)
{
this._InputRef.current.value = this._ParamValue.toString();
//@ts-ignore
e.target.blur();
}
else if (e.keyCode === KeyBoard.Enter || e.keyCode === KeyBoard.Space)
{
if (!this._IsPopoverOpen)
//@ts-ignore
e.target.blur();
e.preventDefault();
}
e.stopPropagation();
}}
onFocus={(e) =>
{
this._InputRef.current.setSelectionRange(0, this._InputRef.current.value.length);
}}
onBlur={(e) =>
{
if (!this._IsPopoverOpen)
{
let val = safeEval(e.target.value);
if (val === this._ParamValue) return;
CommandWrap(() =>
{
for (let dim of this.props.dims)
{
if (dim instanceof AlignedDimension)
{
this.props.changeFunction(dim, val, [this.props.dimParam[0]]);
}
}
}, "修改标注" + this.props.dimParam[1]);
this._ParamValue = val;
}
else
{
e.target.value = FixedNotZero(this._ParamValue, 1);
this._IsPopoverOpen = false;
}
}}
/>
</Tooltip>
</div>
</div>
<Slider
min={this._MinValue}
max={this._MaxValue}
stepSize={this._StepSize}
ref={this._SilderRef}
labelRenderer={false}
onChange={(value) =>
{
if (!CommandState.CommandIng)
commandMachine.CommandStart("更改标注" + this.props.dimParam[1]);
else
if (app.Database.hm.UndoData.CommandName !== "更改标注" + this.props.dimParam[1])
{
AppToaster.show({
message: "命令执行中,无法修改标注" + this.props.dimParam[1],
timeout: 5000,
intent: Intent.WARNING,
}, "change_dim_text");
return false;
}
this._InputRef.current.value = FixedNotZero(value, 1);
this._ParamValue = value;
for (let dim of this.props.dims)
{
if (dim instanceof AlignedDimension)
this.props.changeFunction(dim, value, [this.props.dimParam[0]]);
}
}}
value={this._ParamValue > this._MaxValue ? this._MaxValue : this._ParamValue}
onRelease={() =>
{
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === "更改标注" + this.props.dimParam[1])
commandMachine.CommandEnd();
}}
vertical={false}
/>
</div>
);
}
}

@ -144,6 +144,29 @@
align-items: center;
}
}
.leadLength-editor{
.paramPanel{
&:hover {
background: #E1E8ED;
cursor : pointer;
}
margin-top: 10px;
}
.input_group{
display : flex;
justify-content: space-between;
.numeric_input {
width: 60%;
}
}
}
.bp3-slider.bp3-slider-unlabeled{
margin-top: 5px;
}
}
}
}

@ -1,9 +1,9 @@
import React from "react";
import { observer } from "mobx-react";
import { observable } from "mobx";
import { CommandWrap } from "../../../Editor/CommandMachine";
import { Button, Card, Classes } from "@blueprintjs/core";
import { observable } from "mobx";
import { observer } from "mobx-react";
import React from "react";
import { AlignedDimension } from "../../../DatabaseServices/Dimension/AlignedDimension";
import { CommandWrap } from "../../../Editor/CommandMachine";
export interface Properties_AlignedDimPanelProps
{
ents: AlignedDimension[];
@ -38,7 +38,7 @@ export class Properties_AlignedDimPanel extends React.Component<Properties_Align
{
for (let al of ents)
{
al.toggleLeadOutFlipped();
al.FlippeLead();
}
}, "切换标注引线方向");
}} />
@ -48,7 +48,7 @@ export class Properties_AlignedDimPanel extends React.Component<Properties_Align
{
for (let al of ents)
{
al.toggleLeadOutVisible();
al.ToggleLeadVisible();
}
}, "切换标注引线显示");
}} />

@ -2,19 +2,34 @@ import { Button, Card, Classes, HTMLSelect, Intent, Position, Slider, Tooltip }
import hotkeys from "hotkeys-js-ext";
import { observable } from "mobx";
import { observer } from "mobx-react";
import React from "react";
import React, { RefObject } from "react";
import { Object3D } from "three";
import { end } from "xaop";
import { app } from "../../../ApplicationServices/Application";
import { safeEval } from "../../../Common/eval";
import { KeyBoard, KeyCode } from "../../../Common/KeyEnum";
import { clamp } from "../../../Common/Utils";
import { AlignedDimension } from "../../../DatabaseServices/Dimension/AlignedDimension";
import { Dimension } from "../../../DatabaseServices/Dimension/Dimension";
import { DimStyleKeyCode } from "../../../DatabaseServices/DimStyle/DimstyleKeyCodeEnum";
import { commandMachine, CommandWrap } from "../../../Editor/CommandMachine";
import { CommandState } from "../../../Editor/CommandState";
import { AppToaster } from "../Toaster";
import { DimParamsPanel } from "./DimParamsPanel";
import { PropertiesStore } from "./PropertiesStore";
export enum DimParamsList
{
FootLineLength = "footLineLength",
ArrowSize = "arrowSize",
}
const ParList: [string, string][] =
[
[DimParamsList.FootLineLength, "尺寸界线"],
[DimParamsList.ArrowSize, "箭头尺寸"]
];
export interface Properties_DimPanelProps
{
ents: Dimension[];
@ -23,12 +38,14 @@ export interface Properties_DimPanelProps
@observer
export class Properties_DimPanel extends React.Component<Properties_DimPanelProps, {}>
{
private removeFuncs: Function[] = [];
_RemoveFuncs: Function[] = [];
_DimInputEl = React.createRef<HTMLInputElement>();
_DimParamRefs = new Map<string, RefObject<DimParamsPanel>>();
@observable outlineCheckDims: boolean = true;
@observable private dim_TextSize: number = 60;
@observable private dim_Exact: number = 2;
private dim_InputEl = React.createRef<HTMLInputElement>();
@observable private isPopoverOpen: boolean = false;
@observable _DimTextSize: number = 60;
@observable _DimExact: number = 2;
@observable _IsPopoverOpen: boolean = false;
constructor(p)
{
super(p);
@ -36,8 +53,8 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
if (this.props.ents.length > 0)
{
let numval = this.props.ents[0].TextSize;
this.dim_TextSize = numval;
this.dim_Exact = this.props.ents[0].FractionDigits;
this._DimTextSize = numval;
this._DimExact = this.props.ents[0].FractionDigits;
}
}
@ -51,14 +68,14 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
al.FractionDigits = newExact;
}
}, "修改标注文字精度");
this.dim_Exact = newExact;
this._DimExact = newExact;
}
componentDidMount()
{
this.outlineCheckDims = !(app.Viewer.OutlinePass.selectedObjects.length > 0);
let selectCtrl = app.Editor.SelectCtrl;
this.removeFuncs.push(
this._RemoveFuncs.push(
end(selectCtrl, selectCtrl.UpdateSelectEvent, () =>
{
this.outlineCheckDims = false;
@ -73,42 +90,77 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
if (e.code === KeyCode.KeyZ || e.code === KeyCode.KeyY)
{
let numval = this.props.ents[0].TextSize;
this.dim_TextSize = numval;
this.dim_InputEl.current.value = numval.toString();
this._DimTextSize = numval;
this._DimInputEl.current.value = numval.toString();
}
})
);
if (this.props.ents.length > 0)
{
let numval = this.props.ents[0].TextSize;
this.dim_TextSize = numval;
this.dim_InputEl.current.value = numval.toString();
this._DimTextSize = numval;
this._DimInputEl.current.value = numval.toString();
}
}
componentWillUnmount()
{
for (let f of this.removeFuncs)
for (let f of this._RemoveFuncs)
f();
this.removeFuncs.length = 0;
this._RemoveFuncs.length = 0;
this._DimParamRefs = undefined;
}
private Dim_UseDefault(als: Dimension[])
{
let propsStore = PropertiesStore.GetInstance() as PropertiesStore;
CommandWrap(() =>
{
this.dim_TextSize = 60;
this.dim_Exact = 2;
for (let al of als)
{
al.FractionDigits = 2;
al.TextSize = 60;
al.ColorIndex = 7;
al.ClearDimStyleOverride();
}
this._DimTextSize = als[0].TextSize;
this._DimExact = als[0].FractionDigits;
//颜色
propsStore.colorIndex = 7;//todo 撤销的时候UI颜色没有同步更改
this.dim_InputEl.current.value = "60";
// this.dim_InputEl.setState({ value: "60" });
//文字尺寸
this._DimInputEl.current.value = als[0].TextSize.toString();
for (let [str, ref] of this._DimParamRefs)
{
switch (str)
{
case DimParamsList.FootLineLength:
ref.current.changeElValue(als[0].GetDimStyleValue(DimStyleKeyCode.DIMFXL));
break;
case DimParamsList.ArrowSize:
ref.current.changeElValue(als[0].GetDimStyleValue(DimStyleKeyCode.DIMASZ));
break;
default:
break;
}
}
}, "重置标注形态");
}
private Dim_ChangeLeadLength(dim: AlignedDimension, length: number, keys: string[])
{
for (let key of keys)
{
if (key === DimParamsList.FootLineLength)
{
dim.SetDimStyleOverrideValue(DimStyleKeyCode.DIMFXL, length);
}
else if (key === DimParamsList.ArrowSize)
{
dim.SetDimStyleOverrideValue(DimStyleKeyCode.DIMASZ, length);
}
}
app.Viewer.UpdateRender();
}
render()
{
let ents = this.props.ents;
@ -152,7 +204,7 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
<div>
<span>: </span>
<HTMLSelect
value={this.dim_Exact}
value={this._DimExact}
options={[0, 1, 2, 3, 4, 5]}
onChange={e => this.HandleSelectOnChange(e, ents)}
/>
@ -166,11 +218,11 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
content={"仅限1-999间的数字!"}
position={Position.TOP}
intent={Intent.WARNING}
isOpen={this.isPopoverOpen}
isOpen={this._IsPopoverOpen}
>
<input
ref={this.dim_InputEl}
defaultValue={this.dim_TextSize}
ref={this._DimInputEl}
defaultValue={this._DimTextSize}
style={{ width: "100%" }}
onKeyDown={(e) =>
{
@ -181,7 +233,7 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
}
else if (e.keyCode === KeyBoard.Enter || e.keyCode === KeyBoard.Space)
{
if (!this.isPopoverOpen)
if (!this._IsPopoverOpen)
//@ts-ignore
e.target.blur();
else
@ -193,7 +245,7 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
}}
onFocus={(e) =>
{
this.dim_InputEl.current.setSelectionRange(0, this.dim_InputEl.current.value.length);
this._DimInputEl.current.setSelectionRange(0, this._DimInputEl.current.value.length);
}}
onBlur={(e) =>
{
@ -204,7 +256,7 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
app.Editor.Prompt('文字尺寸仅限1-999间的数字!');
else
{
this.dim_TextSize = val;
this._DimTextSize = val;
CommandWrap(() =>
{
for (let al of this.props.ents)
@ -225,7 +277,7 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
min={20}
max={150}
stepSize={5}
labelStepSize={25}
labelRenderer={false}
onChange={(value) =>
{
if (!CommandState.CommandIng)
@ -241,14 +293,14 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
return false;
}
this.dim_InputEl.current.value = value.toString();
this.dim_TextSize = value;
this._DimInputEl.current.value = value.toString();
this._DimTextSize = value;
for (let al of ents)
{
al.TextSize = this.dim_TextSize;
al.TextSize = this._DimTextSize;
}
}}
value={this.dim_TextSize}
value={this._DimTextSize}
onRelease={() =>
{
if (CommandState.CommandIng && app.Database.hm.UndoData.CommandName === "更改标注文字尺寸")
@ -257,6 +309,23 @@ export class Properties_DimPanel extends React.Component<Properties_DimPanelProp
vertical={false}
/>
</li>
{
ents[0] instanceof AlignedDimension && <div className="leadLength-editor" style={{ display: "block" }}>
{
ParList.map((e) =>
{
let paramRef = React.createRef<DimParamsPanel>();
this._DimParamRefs.set(e[0], paramRef);
return <DimParamsPanel
dimParam={e}
dims={this.props.ents}
ref={paramRef}
changeFunction={this.Dim_ChangeLeadLength}
/>;
})
}
</div>
}
<li>
<Button className={Classes.INTENT_WARNING} text="重置标注为默认" minimal small onClick={() => this.Dim_UseDefault(ents)} />
</li>

@ -75,6 +75,7 @@ export default class ResourceStore
InitClassList = async (class_type: number) =>
{
let res = await getClassList(class_type);
if (!res) return;
this.resourceClass = res.class;
this.resourceParams = res.params;
this.resourceBrands = res.brands;
@ -485,6 +486,7 @@ export default class ResourceStore
InitUserCollectDir = async (order: string) =>
{
let res = await GetUserCollectDir(order);
if (res)
this.userFolder = res.dirs;
};

@ -1232,3 +1232,49 @@ img {
text-overflow: ellipsis;
}
}
#dimConfig{
.bp3-icon.bp3-icon-double-caret-vertical{
margin-top: -1px;
}
}
#AutoDimBoardConfig{
.bp3-dialog-body{
padding : 20px 0 5px 20px;
background-color : white;
.dimGroup{
display : flex;
height : 30px;
margin-bottom : 3px;
&>:first-child{
width : 145px;
}
}
.dimInputGroup{
display : flex;
height : 30px;
margin-bottom : 3px;
&>:first-child{
width : 145px;
}
input{
margin-top : -5px;
}
}
}
.bp3-dialog-footer{
button{
margin-left: 5px;
}
padding: 0 17px 7px;
background-color: white;
}
}

@ -482,3 +482,19 @@ export interface CommonPanelConfigOption
{
orderType: string;
}
export interface IAutoDimBrsOption extends IBaseOption
{
total: boolean;//整体标注
out: boolean;//柜外标注(前视图标注)
inW: boolean;//柜内宽标注
inH: boolean;//柜内高标注
noRepeat: boolean;//删除重复
noSmSize: boolean;//过滤小尺寸
noAppointSize: boolean;//过滤指定尺寸
noInSize: boolean;//空间小于该数值时 不标注内空
noShowMinSize: number;
noShowMinInSize: number;
noShowAppointSizes: string;
useParseGroups: string;
}

@ -1,3 +1,7 @@
//del_exp_start
/*
//del_exp_end
export { IsRect } from "./Common/CurveUtils";
export * from "./DatabaseServices/CADFiler";
export * from "./DatabaseServices/Entity/Arc";
@ -9,3 +13,7 @@ export * from "./GraphicsSystem/BoolOperateUtils";
export { FeedingToolPath } from "./GraphicsSystem/ToolPath/FeedingToolPath";
export * from "./GraphicsSystem/ToolPath/VKnifToolPath";
export * from "./Production/Product";
//del_exp_start
*/
//del_exp_end

@ -1,3 +1,7 @@
//del_exp_start
/*
//del_exp_end
export * from "./DatabaseServices/Entity/Board"; //避免类型错误
export * from "./DatabaseServices/Entity/Circle";
export * from "./DatabaseServices/Entity/Extrude";
@ -20,3 +24,7 @@ export * from "./Reactor/RoomHoleReactor";
//Db Status
export * from "./Common/Status";
export * from "./Add-on/Purge";
//del_exp_start
*/
//del_exp_end

Loading…
Cancel
Save