!1212 功能:一键布局,命令onekeylayout

pull/1212/MERGE
ZoeLeeFZ 4 years ago committed by ChenX
parent 8448f856c2
commit 05b404cd17

@ -3,7 +3,6 @@ import { Board } from "../../DatabaseServices/Entity/Board";
import { HardwareCompositeEntity } from "../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { CuttingBoardByHardware } from "./CuttingUtils2";
import { CommandNames } from "../../Common/CommandNames";
import { CommandServer } from "../../DatabaseServices/CommandServer";
export class HardwareCuttingReactor
{
@ -14,6 +13,7 @@ export class HardwareCuttingReactor
app.CommandReactor.OnCommandEnd((cmdName, changeObjects, createObjects) =>
{
if (app.Viewer.isLayout) return;
if (!this.EnableHardware && !hardwareCmds.includes(cmdName)) return;
let brs: Board[] = [];

@ -21,6 +21,8 @@ export class DrillingReactor
{
app.CommandReactor.OnCommandEnd((cmdName: string, changeObjects, createObjects) =>
{
if (app.Viewer.isLayout) return;
this.Enable = userConfig.openDrillingReactor;
if (cmdName === CommandNames.Copy)
{

@ -7,12 +7,41 @@ import { Vector3 } from "three";
import { DownPanelStore } from "../UI/Store/DownPanelStore";
import { Entity } from "../DatabaseServices/Entity/Entity";
import { ObjectId } from "../DatabaseServices/ObjectId";
import { AppToaster } from "../UI/Components/Toaster";
import { Intent } from "@blueprintjs/core";
import { Sleep } from "../Common/Sleep";
import { Board } from "../DatabaseServices/Entity/Board";
import { BoardOpenDir } from "../UI/Store/BoardInterface";
import { HardwareCompositeEntity } from "../DatabaseServices/Hardware/HardwareCompositeEntity";
async function GetViewportInfo()
{
let isAll = true;
let isAll = false;
let ens: Entity[] = [];
const downStore = (DownPanelStore.GetInstance() as DownPanelStore);
downStore.isLayout = false;
const SelectEns = async () =>
{
let enRes = await app.Editor.GetSelection({
Msg: "选择指定布局的柜体",
});
if (enRes.Status === PromptStatus.Cancel)
{
downStore.isLayout = true;
isAll = true;
return;
}
else
{
ens = enRes.SelectSet.SelectEntityList;
downStore.isLayout = true;
}
};
await SelectEns();
while (true)
{
@ -35,22 +64,8 @@ async function GetViewportInfo()
isAll = !isAll;
if (!isAll)
{
const downStore = (DownPanelStore.GetInstance() as DownPanelStore);
downStore.isLayout = false;
let enRes = await app.Editor.GetSelection({
Msg: "选择指定布局的柜体",
});
if (enRes.Status === PromptStatus.Cancel)
{
downStore.isLayout = true;
return;
}
else
{
ens = enRes.SelectSet.SelectEntityList;
downStore.isLayout = true;
}
await SelectEns();
}
else
{
@ -112,47 +127,82 @@ export class Draw4Viewport implements Command
const {
p1, p2, ens
} = data;
AppToaster.show({
message: "正在生成布局,请稍后",
timeout: 0,
intent: Intent.PRIMARY
}, "layout");
await Sleep(16);
const vps = Get4Viewport(p1, p2, ens);
vps.forEach(p => app.Database.LayoutSpace.Append(p));
AppToaster.dismiss('layout');
}
}
}
let needHideIds: ObjectId[] = [];
export function Get4Viewport(p1: Vector3, p2: Vector3, ens: Entity[], isHideDoor = false)
{
let needHideIds: ObjectId[] = [];
if (ens.length > 0)
{
for (let en of app.Database.ModelSpace.Entitys)
{
if (!ens.includes(en))
needHideIds.push(en.Id);
}
}
if (ens.length > 0)
{
for (let en of app.Database.ModelSpace.Entitys)
{
if (!ens.includes(en))
needHideIds.push(en.Id);
}
}
let left = Math.min(p1.x, p2.x);
let bottom = Math.min(p1.y, p2.y);
let width = Math.abs(p1.x - p2.x);
let height = Math.abs(p1.y - p2.y);
let left = Math.min(p1.x, p2.x);
let bottom = Math.min(p1.y, p2.y);
let width = Math.abs(p1.x - p2.x);
let height = Math.abs(p1.y - p2.y);
let vp1 = new ViewportEntity(width / 2, height / 2);
vp1.Position = new Vector3(left, bottom);
let vp1 = new ViewportEntity(width / 2, height / 2);
vp1.Position = new Vector3(left, bottom);
let vp2 = new ViewportEntity(width / 2, height / 2);
vp2.Position = new Vector3(left + width / 2, bottom);
vp2.camera.LookAt(new Vector3(1, 1, -1));
let vp2 = new ViewportEntity(width / 2, height / 2);
vp2.Position = new Vector3(left + width / 2, bottom);
vp2.camera.LookAt(new Vector3(1, 1, -1));
let vp3 = new ViewportEntity(width / 2, height / 2);
vp3.camera.LookAt(new Vector3(-1));
vp3.Position = new Vector3(left + width / 2, bottom + height / 2);
let vp3 = new ViewportEntity(width / 2, height / 2);
vp3.camera.LookAt(new Vector3(-1));
vp3.Position = new Vector3(left + width / 2, bottom + height / 2);
let vp4 = new ViewportEntity(width / 2, height / 2);
vp4.camera.LookAt(new Vector3(0, 1));
vp4.Position = new Vector3(left, bottom + height / 2);
let vp4 = new ViewportEntity(width / 2, height / 2);
vp4.camera.LookAt(new Vector3(0, 1));
vp4.Position = new Vector3(left, bottom + height / 2);
for (let id of needHideIds)
for (let id of needHideIds)
{
vp1.hideObjectIds.add(id);
vp2.hideObjectIds.add(id);
vp3.hideObjectIds.add(id);
vp4.hideObjectIds.add(id);
}
if (isHideDoor)
for (let en of ens)
{
if (en instanceof Board)
{
vp1.hideObjectIds.add(id);
vp2.hideObjectIds.add(id);
vp3.hideObjectIds.add(id);
vp4.hideObjectIds.add(id);
if (en.OpenDir !== BoardOpenDir.None)
{
vp4.hideObjectIds.add(en.Id);
}
}
else if (en instanceof HardwareCompositeEntity)
{
if (en.HardwareOption.model.endsWith("开门板")
|| en.HardwareOption.name.includes("铰链")
|| en.HardwareOption.name.includes("门板")
|| en.HardwareOption.name.includes("拉手"))
{
vp4.hideObjectIds.add(en.Id);
}
}
[vp1, vp2, vp3, vp4].forEach(p => app.Database.LayoutSpace.Append(p));
}
}
return [
vp1, vp2, vp3, vp4
];
}

@ -4,11 +4,19 @@ import { Circle } from '../DatabaseServices/Entity/Circle';
import { Line } from '../DatabaseServices/Entity/Line';
import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult';
import { Text } from '../DatabaseServices/Text/Text';
import { Log } from '../Common/Log';
export class Command_Explode implements Command
{
async exec()
{
if (app.Viewer.CurrentViewport)
{
Log("视口模式下暂不支持");
return;
}
let ssRes = await app.Editor.GetSelection({ UseSelect: true });
if (ssRes.Status != PromptStatus.OK) return;
@ -16,7 +24,7 @@ export class Command_Explode implements Command
for (let en of ss.SelectEntityList)
{
if (en instanceof Line || en instanceof Arc || en instanceof Circle)
if (en instanceof Line || en instanceof Arc || en instanceof Circle || en instanceof Text)
{
app.Editor.Prompt('无法分解');
continue;
@ -26,7 +34,7 @@ export class Command_Explode implements Command
for (let e of ens)
{
app.Database.ModelSpace.Append(e);
app.LayoutTool.AppendDatabaseSpace(e);
}
}
}

@ -78,9 +78,6 @@ export class Command_Move implements Command
}
}
en.ApplyMatrix(moveMatrix);
//不更新集合体将显示错误,不知道为啥
if (en instanceof Text && (app.Viewer.isLayout || !app.Viewer.UsePass))
en.Update(UpdateDraw.Geometry);
}
}
}

@ -0,0 +1,228 @@
import { Command } from "../../Editor/CommandMachine";
import { app } from "../../ApplicationServices/Application";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Entity } from "../../DatabaseServices/Entity/Entity";
import { CompositeEntity } from "../../DatabaseServices/Entity/CompositeEntity";
import { SweepSolid } from "../../DatabaseServices/3DSolid/SweepSolid";
import { Hole } from "../../DatabaseServices/3DSolid/Hole";
import { ParseBoardList } from "../../Common/BoardUtil";
import { Box3Ext } from "../../Geometry/Box";
import { PostJson, RequestStatus } from "../../Common/Request";
import { ToplineUrls } from "../../Common/HostUrl";
import { AppToaster } from "../../UI/Components/Toaster";
import { Intent } from "@blueprintjs/core";
import { inflate, GroupFileIn } from "../../Common/SerializeMaterial";
import { Box3, Vector3 } from "three";
import { Get4Viewport } from "../DrawViewport";
import { ViewportEntity } from "../../DatabaseServices/ViewportEntity";
import { GroupRecord } from "../../DatabaseServices/GroupTableRecord";
import { Log } from "../../Common/Log";
import { Sleep } from "../../Common/Sleep";
import { AlignedDimension } from "../../DatabaseServices/Dimension/AlignedDimension";
import { PromptStatus } from "../../Editor/PromptResult";
export class OneKeyLayout implements Command
{
async exec()
{
if (!app.Viewer.isLayout)
{
Log("仅能在布局模式下使用");
return;
}
let curves: Entity[];
let frameWidth: number;
let p1: Vector3;
let p2: Vector3;
const handleEntitys = (ens: Entity[]) =>
{
let box = new Box3();
ens.reduce((b, e) =>
{
return b.union(e.BoundingBox);
}, box);
curves = ens;
let basePt = box.min;
frameWidth = box.getSize(new Vector3).x;
ens.forEach(e => e.Position = e.Position.sub(basePt));
if (p1)
{
p1.sub(basePt);
p2.sub(basePt);
}
};
while (true)
{
let gRes = await app.Editor.GetEntity({
Msg: "选择一键布局的图框",
KeyWordList: [{ msg: "使用默认", key: "D" }, { msg: "视口范围", key: "R" }],
NotNone: true,
Filter: {
filterFunction: (o, e) => !!e.GroupId
}
});
if (gRes.Status === PromptStatus.OK)
{
let ens = (gRes.Entity.GroupId.Object as GroupRecord).Entitys.map(i => i.Object.Clone()) as Entity[];
handleEntitys(ens);
break;
}
else if (gRes.Status === PromptStatus.Keyword)
{
if (gRes.StringResult === "D")
{
let data = await PostJson(ToplineUrls.get, {
dir_id: "",
name: "默认图框",
});
if (data.err_code === RequestStatus.Ok && Number(data.count))
{
data = await PostJson(ToplineUrls.detail, { topline_id: data.toplines[0].topline_id });
if (data.err_code === RequestStatus.Ok)
{
let file = inflate(data.toplines.file);
let ens = GroupFileIn(JSON.parse(file));
handleEntitys(ens);
}
}
break;
}
else if (gRes.StringResult === "R")
{
const rRes = await app.Editor.GetRectPoint();
if (rRes.Status === PromptStatus.OK)
{
p1 = rRes.Point1UCS;
p2 = rRes.Point2UCS;
}
else return;
}
}
else return;
}
if (!curves)
{
AppToaster.show({
message: "不存在默认图框",
timeout: 2000,
intent: Intent.DANGER
});
return;
}
let boardList: Board[] = [];
let hardwares: (CompositeEntity | SweepSolid)[] = [];
let others: Entity[] = [];
for (let en of app.Database.ModelSpace.Entitys)
{
if (en?.Id && !en.IsErase && en.Visible)
{
if (en instanceof Board)
boardList.push(en);
else if (en instanceof CompositeEntity || en instanceof SweepSolid)
hardwares.push(en);
else if (!(en instanceof Hole))
others.push(en);
}
}
if (boardList.length === 0)
{
Log("没找到柜体");
return;
}
const ocsInv = boardList[0].SpaceOCSInv;
let boxBoardMap = ParseBoardList([...boardList, ...hardwares], ocsInv);
const useEntity = new WeakSet<Entity>();
let boxMap = new WeakMap<Entity, Box3Ext>();
for (let [box, bs] of boxBoardMap)
{
for (let en of others)
{
if (useEntity.has(en)) continue;
let b = boxMap.get(en);
if (!b)
{
b = en.BoundingBox as Box3Ext;
boxMap.set(en, b);
}
if (b.isEmpty)
{
if (en instanceof AlignedDimension)
{
let dist = box.distanceToPoint(en.FootP1.applyMatrix4(ocsInv));
if (dist <= 50)
{
useEntity.add(en);
(bs as Entity[]).push(en);
}
}
}
else if (b.intersectsBox(box))
{
(bs as Entity[]).push(en);
useEntity.add(en);
box.union(b);
}
}
}
let left = 600;
let bottom = 230;
let vpsWidth = 2320;
let vpsHeight = 1820;
const DIST = 1 / 8 * frameWidth;
if (p1 && p2)
{
left = Math.min(p1.x, p2.x);
bottom = Math.min(p1.y, p2.y);
vpsWidth = Math.abs(p1.x - p2.x);
vpsHeight = Math.abs(p1.y - p2.y);
}
const Total_Length = frameWidth + DIST;
let vps: ViewportEntity[] = [];
AppToaster.show({
message: "正在生成布局,请稍后",
timeout: 0,
intent: Intent.PRIMARY
}, "onekey");
await Sleep(16);
let i = 0;
for (let [, bs] of boxBoardMap)
{
let x = left + i * Total_Length;
vps.push(...Get4Viewport(new Vector3(x, bottom), new Vector3(x + vpsWidth, bottom + vpsHeight), bs, true));
let g = new GroupRecord();
app.Database.GroupTable.Add(g);
for (let c of curves)
{
let cloneC = c.Clone();
app.LayoutTool.AppendDatabaseSpace(cloneC);
g.Entitys.push(cloneC.Id);
cloneC.Position = cloneC.Position.add(new Vector3(i * Total_Length));
}
i++;
}
vps.forEach(v => app.Database.LayoutSpace.Append(v));
AppToaster.dismiss('onekey');
}
}

@ -1,14 +1,14 @@
import { Board } from "../DatabaseServices/Entity/Board";
import { Matrix4, Box3, Vector3 } from "three";
import { Matrix4, Vector3 } from "three";
import { Entity } from "../DatabaseServices/Entity/Entity";
import { GetMirrorMat } from "./Matrix4Utils";
import { MoveMatrix } from "../Geometry/GeUtils";
import { Box3Ext } from "../Geometry/Box";
/**分析不同柜体 */
export function ParseBoardList(borads: Board[], ocsInv?: Matrix4)
export function ParseBoardList(borads: Entity[], ocsInv?: Matrix4)
{
let boxMap: Map<Box3, Board> = new Map();
let boxes: Box3[] = [];
let boxMap: Map<Box3Ext, Entity> = new Map();
let boxes: Box3Ext[] = [];
if (!ocsInv)
ocsInv = borads[0].SpaceOCSInv;
@ -20,7 +20,7 @@ export function ParseBoardList(borads: Board[], ocsInv?: Matrix4)
boxMap.set(box, br);
}
let boardMap: Map<Box3, Board[]> = new Map();
let boardMap: Map<Box3Ext, Entity[]> = new Map();
while (boxes.length > 0)
{
let originBox = boxes.shift();
@ -29,7 +29,7 @@ export function ParseBoardList(borads: Board[], ocsInv?: Matrix4)
{
let remBoxes = boxes.filter(b =>
{
if (originBox.intersectsBox(b))
if (originBox.intersectsBox(b, 10))
{
originBox.union(b);
brs.push(boxMap.get(b));

@ -174,4 +174,5 @@ export enum CommandNames
MView4 = "MVIEW4",//添加视口
ShowFrame = "SHOWFRAME",//添加视口
UnGroup = "UNGROUP",//添加视口
OneKeyLayout = "ONEKEYLAYOUT",//添加视口
}

@ -8,7 +8,8 @@ export function DisposeThreeObj(obj: Object3D)
for (let o of obj.children)
{
let oany = o as any;
if (oany.geometry)
//文字的geometry缓存保留下来
if (oany.geometry && oany.geometry.name !== "Text")
oany.geometry.dispose();
DisposeThreeObj(o);
o.parent = null;

@ -11,6 +11,7 @@ export class BoardLinesReactor
{
app.CommandReactor.OnCommandEnd((cmdName: string, changeObjects: CADObject[], createObjects: CADObject[]) =>
{
if (app.Viewer.isLayout) return;
let hasMaxSize = false;
for (let ent of changeObjects)
{

@ -7,6 +7,7 @@ import { Factory } from '../CADFactory';
import { CADFiler } from '../CADFiler';
import { Entity } from '../Entity/Entity';
import { FontLoader } from './FontLoader';
import { UpdateDraw } from '../../Common/Status';
export enum TextAligen
{
@ -15,6 +16,8 @@ export enum TextAligen
LeftDown = 10, Down = 8, RightDown = 12,
}
const ShapeCache = new Map<string, ShapeGeometry>();
/**
*
*/
@ -72,7 +75,7 @@ export class Text extends Entity
{
this.WriteAllObjectRecord();
this._Height = v;
this.Update();
this.Update(UpdateDraw.Geometry);
}
//创建字体对象
async AsyncUpdateDrawObject(obj: Object3D, renderType: RenderType)
@ -89,9 +92,18 @@ export class Text extends Entity
let f = FontLoader.GetLoader(this._FontName);
await f.LoadGlyphs(this.TextString);
await f.AwaitLoaded();
let shapes: Shape[] = f.Font.generateShapes(this._TextString, this._Height);
let geometry = new ShapeGeometry(shapes);
geometry.computeBoundingBox();
const key = this._FontName + this._TextString + this._Height;
let geometry = ShapeCache.get(key);
if (!geometry)
{
let shapes = f.Font.generateShapes(this._TextString, this._Height);
geometry = new ShapeGeometry(shapes);
geometry.name = "Text";
geometry.computeBoundingBox();
ShapeCache.set(key, geometry);
}
mesh.geometry = geometry;
let color = renderType === RenderType.Print ? 256 : this.ColorIndex;
@ -154,6 +166,16 @@ export class Text extends Entity
}
}
}
protected ApplyScaleMatrix(m: Matrix4): this
{
this.WriteAllObjectRecord();
let p1 = this.Position;
let p2 = new Vector3(0, this._Height).applyMatrix4(this.OCS);
[p1, p2].forEach(p => p.applyMatrix4(m));
this.Position = p1;
this.Height = p1.distanceTo(p2);
return this;
}
//重载
protected OnlyRenderType = true;

@ -18,6 +18,7 @@ import { CompositeEntity } from "./Entity/CompositeEntity";
import { DisposeThreeObj } from "../Common/Dispose";
import { VisualSpaceBox } from "../Editor/VisualSpaceBox";
import { Board } from "./Entity/Board";
import { HardwareCompositeEntity } from "./Hardware/HardwareCompositeEntity";
@Factory
export class ViewportEntity extends Entity
@ -182,7 +183,7 @@ export class ViewportEntity extends Entity
if (box.isEmpty())
box.set(new Vector3(), new Vector3(1000 * (this.Width / this.Height), 1000, 1000));
this.camera.ZoomExtensBox3(box);
this.camera.Zoom(1.5);
this.camera.Zoom(1.2);
}
get RenderType()
{
@ -212,6 +213,10 @@ export class ViewportEntity extends Entity
&& !(en instanceof ViewportEntity)
&& !(en instanceof VisualSpaceBox))
{
//不渲染铰链
if (en instanceof HardwareCompositeEntity && en.HardwareOption.name.includes("铰链"))
return;
let ens: Entity[];
if (en instanceof Board)
{

@ -191,6 +191,7 @@ import { Polyline2Winerack } from "../Add-on/DrawWineRack/Polyline2Winerack";
import { DrawViewport, Draw4Viewport } from "../Add-on/DrawViewport";
import { RenderType } from "../GraphicsSystem/RenderType";
import { ShowFrmae } from "../Add-on/Template/ShowFrame";
import { OneKeyLayout } from "../Add-on/Viewport/OneKeyLayout";
export function registerCommand()
{
@ -534,6 +535,7 @@ export function registerCommand()
commandMachine.RegisterCommand(CommandNames.MView, new DrawViewport());
commandMachine.RegisterCommand(CommandNames.MView4, new Draw4Viewport());
commandMachine.RegisterCommand(CommandNames.ShowFrame, new ShowFrmae());
commandMachine.RegisterCommand(CommandNames.OneKeyLayout, new OneKeyLayout());
}
export async function RegistCustomCommand()

@ -265,7 +265,7 @@ export class LayoutTool
for (let en of selects)
{
if (en instanceof ViewportEntity) continue;
if (!en || en instanceof ViewportEntity) continue;
for (let vp of vps)
{

@ -266,7 +266,7 @@ export class Viewer
let width = Math.abs(p2.x - p1.x);
let height = Math.abs(p2.y - p1.y);
if (width <= 0 || height <= 0)
if (width <= 2 || height <= 2)
continue;
viewport.camera.SetSize(width, height);

@ -41,6 +41,7 @@ export class RelevanceCuttingReactor
{
app.CommandReactor.OnCommandEnd((cmdName, changeObjects, createObjects) =>
{
if (app.Viewer.isLayout) return;
UpdateRelevanceGroove([...changeObjects, ...createObjects]);
});

@ -1462,6 +1462,16 @@ export const CommandList: ICommand[] = [
chName: "图框管理",
chDes: "图框管理",
},
{
icon: IconEnum.OneKeyLayout,
typeId: "file",
link: "#",
defaultCustom: "OKLY",
command: CommandNames.OneKeyLayout,
type: "文件",
chName: "一键布局",
chDes: "一键布局",
},
{
icon: IconEnum.Group,
typeId: "file",

@ -19,6 +19,7 @@ import { observer } from 'mobx-react';
import { Vector3, Box3, Matrix4 } from 'three';
import { CommandWrap } from '../../../Editor/CommandMachine';
import { JigUtils } from '../../../Editor/JigUtils';
import { Region } from '../../../DatabaseServices/Entity/Region';
export interface IFrameManageProps
{
@ -178,7 +179,8 @@ export class FrameManage extends React.Component<IFrameManageProps> {
{
if (id?.Object && !id.IsErase)
{
ens.push(id.Object.Clone() as Entity);
if (id.Object instanceof Curve || id.Object instanceof Region || id.Object instanceof Text)
ens.push(id.Object.Clone());
}
}
let fileJson = GroupOut(ens);

@ -168,6 +168,7 @@ export class TopToolBar extends React.Component<{}, {}>
{ svg: IconEnum.ShowFrame, title: "图框管理", command: CommandNames.ShowFrame },
{ svg: IconEnum.Mview, title: "单视口", command: CommandNames.MView },
{ svg: IconEnum.Mview4, title: "多视口", command: CommandNames.MView4 },
{ svg: IconEnum.OneKeyLayout, title: "一键布局", command: CommandNames.OneKeyLayout },
{ svg: IconEnum.Print, title: "打印", command: CommandNames.Print },
];

@ -175,4 +175,5 @@ export enum IconEnum
Mview = "MVIEW.svg",
Mview4 = "MVIEW4.svg",
ShowFrame = "SHOWFRAME.svg",
OneKeyLayout = "ONEKEYLAYOUT.svg",
}

Loading…
Cancel
Save