!1378 功能: 矩形转层板立板,命令R2B2

pull/1378/MERGE
ZoeLeeFZ 4 years ago committed by ChenX
parent e6a71253af
commit 43ab04e521

@ -0,0 +1,121 @@
import { Button, Card, H5, Intent } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import React, { Component } from 'react';
import { app } from '../../../ApplicationServices/Application';
import { CheckObjectType } from '../../../Common/CheckoutVaildValue';
import { Input5Or4Component, Notes, SetBoardDataBlock } from '../../../UI/Components/Board/BoardCommon';
import { BoardModalType } from '../../../UI/Components/Board/BoardModal';
import { CommonModal } from '../../../UI/Components/Modal/ModalContainer';
import { ModalState } from '../../../UI/Components/Modal/ModalInterface';
import { AppToaster } from '../../../UI/Components/Toaster';
import { R2B2Store } from '../R2B2Store';
import { SelectDrillType } from '../R2BCommon';
const CabPars = [
["depthExpr", "柜深"], ["maxThickness", "最大板厚"],
];
const ShrinkPars = [
["vertialShrink", "立板"], ["layerShrink", "层板"],
];
@observer
export class R2b2Panel extends Component<{ store: R2B2Store; }>
{
render()
{
const { store } = this.props;
return (
<CommonModal
title="矩形变板件"
close={this.close}
store={store}
type={BoardModalType.R2B2}
footerChildren={
<>
<Button
text="确定"
intent={Intent.SUCCESS}
onClick={this.confirm}
/>
<Button
text="取消"
intent={Intent.DANGER}
onClick={this.close}
/>
</>
}
>
<Card className="flex r2b2">
<div style={{ width: 250 }}>
<H5></H5>
<SetBoardDataBlock
type={CheckObjectType.R2B}
className="flexWrap"
pars={CabPars}
option={store.option}
uiOption={store.UIOption}
/>
<H5></H5>
<SetBoardDataBlock
type={CheckObjectType.R2B}
className="flexWrap"
pars={ShrinkPars}
option={store.option}
uiOption={store.UIOption}
/>
<H5></H5>
<SelectDrillType
option={store.option}
style={{
width: "100%",
height: 20,
lineHeight: "20px"
}}
/>
<H5></H5>
<Input5Or4Component
type={CheckObjectType.BR}
showDirectionIcon={true}
hasCenter={false}
optKey=""
upKey="sealedUp"
downKey="sealedDown"
leftKey="sealedLeft"
rightKey="sealedRight"
option={store.option}
isShowEditor={true}
/>
</div>
<div>
<Notes
remarks={store.option.remarks}
/>
</div>
</Card>
</CommonModal>
);
}
private close = () =>
{
app.Editor.ModalManage.Destory();
};
private confirm = () =>
{
let error = this.props.store.HasInvailValue();
if (error)
{
AppToaster.show({
message: "存在无效数值,请修正",
timeout: 3000,
intent: Intent.DANGER
});
return;
}
app.Editor.ModalManage.DestoryAndExec(
{
Status: ModalState.Ok,
Data: { cname: "矩形变层板立板" }
}
);
};
}

@ -6,15 +6,17 @@
width: 4rem;
}
}
.undefined.br-set{
>span:first-child{
.undefined.br-set {
>span:first-child {
width: 4.5rem;
}
}
.select-drillType
{
.select-drillType {
width: 9rem;
}
.note-card {
padding: 10px !important;
@ -65,3 +67,20 @@
#rec2Br .notes>div>input:last-child {
width: 70%;
}
#modal .r2b2 {
.selectDrillType {
width: 80%;
}
.flexWrap {
width: 100%;
.br-set {
span {
width: 60px;
}
}
}
}

@ -0,0 +1,65 @@
import { observable, toJS } from "mobx";
import { begin } from "xaop";
import { CheckObjectType, CheckoutValid } from "../../Common/CheckoutVaildValue";
import { DataAdapter } from "../../Common/DataAdapter";
import { DefaultR2b2Option } from "../../Editor/DefaultConfig";
import { userConfig } from "../../Editor/UserConfig";
import { IConfigOption } from "../../UI/Components/Board/UserConfig";
import { IUiOption } from "../../UI/Store/BoardInterface";
import { IConfigStore } from "../../UI/Store/BoardStore";
import { IRect2Br2Option } from "./R2bInterface";
export class R2B2Store implements IConfigStore
{
@observable configName = "默认";
@observable configsNames: string[] = [];
@observable option: IRect2Br2Option = { ...DefaultR2b2Option, remarks: Array.from({ length: 12 }, () => ["", ""]) };
@observable uiOption: IUiOption<IRect2Br2Option>;
constructor()
{
begin(userConfig, userConfig.SetDrillConfigsEvent, () =>
{
this.InitDrillType();
});
}
get UIOption(): IUiOption<IRect2Br2Option>
{
if (!this.uiOption)
this.uiOption = DataAdapter.ConvertUIData(this.option);
return this.uiOption;
}
protected InitDrillType()
{
let drilltypes = [...userConfig.DrillConfigs.keys(), "不排"];
if (drilltypes.length > 0)
{
if (!drilltypes.includes(this.option.drillType))
this.option.drillType = drilltypes[0];
}
}
InitOption()
{
Object.assign(this.option, DefaultR2b2Option, { remarks: Array.from({ length: 12 }, () => ["", ""]) });
if (this.uiOption)
Object.assign(this.uiOption, DataAdapter.ConvertUIData(this.option));
}
SaveConfig()
{
return {
option: toJS(this.option)
};
}
UpdateOption(conf: IConfigOption<IRect2Br2Option>)
{
Object.assign(this.option, conf.option);
if (this.uiOption)
Object.assign(this.uiOption, DataAdapter.ConvertUIData(conf.option));
this.InitDrillType();
}
HasInvailValue()
{
return CheckoutValid.HasInvailValue(this.UIOption, CheckObjectType.R2B);
}
}
export const r2b2Store = new R2B2Store();

@ -1,10 +1,11 @@
import * as React from 'react';
import { Checkbox, Classes } from '@blueprintjs/core';
import { Checkbox, Classes, HTMLSelect } from '@blueprintjs/core';
import { Rec2BrStore } from './Rec2BrStore';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import { arrayRemove } from '../../Common/ArrayExt';
import { updateBoardInfoStore } from '../../UI/Store/UpdateBoardInfoStore';
import { userConfig } from '../../Editor/UserConfig';
export interface ISelectBrConfigNameProps
{
@ -61,3 +62,38 @@ export class SelectBrConfigName extends React.Component<ISelectBrConfigNameProps
arrayRemove(this.configNames, "");
};
}
interface ISelectDrillTypeProps
{
option: { drillType: string; };
onchange?: (e: string) => void;
style?: React.CSSProperties;
}
@observer
export class SelectDrillType extends React.Component<ISelectDrillTypeProps>
{
render()
{
const { option } = this.props;
const selectOptions = userConfig.DrillConfigs.size > 0 ? [...userConfig.DrillConfigs.keys(), "不排"] : [];
return (
<HTMLSelect
className="selectDrillType"
value={option.drillType}
style={this.props.style ?? {}}
options={selectOptions}
onChange={this.handleChange}
/>
);
}
private handleChange = (e: React.ChangeEvent) =>
{
let val = (e.target as HTMLSelectElement).value;
this.props.option.drillType = val;
if (this.props.onchange)
this.props.onchange(val);
};
}

@ -1,4 +1,4 @@
import { IBaseOption, IGrooveOption } from "../../UI/Store/BoardInterface";
import { DrillType, IBaseOption, IGrooveOption } from "../../UI/Store/BoardInterface";
import { TemplateRecord } from "../../DatabaseServices/Template/TemplateRecord";
import { EBoardKeyList } from "../../Common/BoardKeyList";
@ -67,3 +67,17 @@ export interface IRec2BrOption extends IBaseOption
behindIsRelative: boolean;
footerThickness: number;
}
export interface IRect2Br2Option extends IBaseOption
{
depthExpr: string;
maxThickness: number;
layerShrink: number;
vertialShrink: number;
[EBoardKeyList.DrillType]: DrillType | string;
[EBoardKeyList.UpSealed]: string;
[EBoardKeyList.DownSealed]: string;
[EBoardKeyList.LeftSealed]: string;
[EBoardKeyList.RightSealed]: string;
remarks: [string, string][];
}

@ -0,0 +1,275 @@
import { toJS } from "mobx";
import { Box3, Matrix4, Object3D, Vector3 } from "three";
import { app } from "../../ApplicationServices/Application";
import { EBoardKeyList } from "../../Common/BoardKeyList";
import { GetRectData } from "../../Common/CurveUtils";
import { safeEval } from "../../Common/eval";
import { Buy2To3 } from "../../Common/HostUrl";
import { Log } from "../../Common/Log";
import { FixDigits } from "../../Common/Utils";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { isParallelTo, XAxis, YAxis, ZAxis } from "../../Geometry/GeUtils";
import { ClampSpaceParseRay } from "../../Geometry/SpaceParse/ClampSpaceParseRay";
import { ISpaceParse } from "../../Geometry/SpaceParse/ISpaceParse";
import { PointSelectBoards } from "../../Geometry/SpaceParse/PointSelectBoards";
import { RenderType } from "../../GraphicsSystem/RenderType";
import { AppConfirm } from "../../UI/Components/Common/Confirm";
import { BoardType, FaceDirection } from "../../UI/Store/BoardInterface";
import { TopPanelStore } from "../../UI/Store/TopPanelStore";
import { R2b2Panel } from "./Modals/R2b2";
import { r2b2Store } from "./R2B2Store";
import { IRect2Br2Option } from "./R2bInterface";
export class Rect2Board implements Command
{
async exec()
{
const tpStore = TopPanelStore.GetInstance() as TopPanelStore;
if (!tpStore.canUse2to3)
{
let res = await AppConfirm.show({ message: "您还未购买该增值包,前往购买?" });
if (res)
{
window.open(Buy2To3);
}
return;
}
let ss = await app.Editor.GetSelection({
Msg: "请选择曲线:",
UseSelect: true,
Filter: { filterTypes: [Polyline] }
});
if (ss.Status === PromptStatus.Cancel) return;
let pls = ss.SelectSet.SelectEntityList as Polyline[];
app.Editor.ModalManage.RenderModal(R2b2Panel, { store: r2b2Store });
app.Editor.ModalManage.SetCallback(async () =>
{
await tool.Do(pls, toJS(r2b2Store.option));
});
}
}
const PlCache = new Map<Polyline, Polyline>();
class Rect2BoardTool2
{
private spaceParse: ISpaceParse;
private _option: IRect2Br2Option;
async Do(pls: Polyline[], option: IRect2Br2Option)
{
for (let [k,] of PlCache)
k = null;
PlCache.clear();
//默认认为用户传进来的pls都平行,都在一个平面内
if (!pls || pls.length === 0) return;
this._option = option;
let ucs = new Matrix4().makeBasis(XAxis, ZAxis, YAxis.clone().negate());
let ucsinv = new Matrix4().getInverse(ucs);
// pls = pls.filter(pl => CurveInOCS(pl, ucs, ucsinv));
const clonePls: Polyline[] = [];
for (let l of pls)
{
let cl = l.Clone();
clonePls.push(cl);
PlCache.set(cl, l);
}
const totalBrs: Board[] = [];
for (let pl of clonePls)
{
const box = pl.BoundingBox;
const spaceParse = await this.GetSpaceParse(box);
if (!spaceParse.ParseOK)
{
Log("没有对应的空间");
return;
}
pl.ApplyMatrix(spaceParse.SpaceOCSInv);
if (!isParallelTo(pl.Normal, ZAxis))
{
pl.ApplyMatrix(ucsinv);
}
pl.Position = pl.Position.setZ(0);
this.ParsePolyline(pl);
this.spaceParse = spaceParse;
const size = spaceParse.Size;
const depth = safeEval(option.depthExpr, { L: size.x, W: size.y, H: size.z });
totalBrs.push(...this.DrawBoard([pl], depth));
}
totalBrs.forEach(b => app.Database.ModelSpace.Append(b));
}
private ParsePolyline(pl: Polyline)
{
let firstDev = pl.GetFistDeriv(0);
let size: Vector3;
let box: Box3;
if (isParallelTo(firstDev, XAxis) || isParallelTo(firstDev, YAxis))
{
box = pl.BoundingBox;
size = box.getSize(new Vector3);
}
else
{
let rd = GetRectData(pl);
if (rd.isRect)
{
pl.TempData = rd;
box = rd.box;
size = rd.size;
}
else
{
box = pl.BoundingBox;
size = box.getSize(new Vector3);
}
}
pl.__CacheSize__ = size;
pl.__CacheBox__ = box;
}
private async GetSpaceParse(box: Box3)
{
let center = box.getCenter(new Vector3);
const objects: Object3D[] = [];
for (let br of app.Database.ModelSpace.Entitys)
{
if (!br.IsErase && br.Visible && br instanceof Board)
{
objects.push(br.GetDrawObjectFromRenderType(RenderType.Physical));
}
}
app.Viewer.WorldToScreen(center);
let ptSelect = new PointSelectBoards(center, app.Viewer, objects);
const SpaceParse = new ClampSpaceParseRay(ptSelect.SelectBoards).SetRay(ptSelect.Ray);
await SpaceParse.Parse();
return SpaceParse;
}
DrawBoard(pls: Polyline[], depth: number)
{
let maxThickness = this._option.maxThickness;
let spaceOCS = this.spaceParse.SpaceOCS;
let min = this.spaceParse.SpaceBox.min;
const verShrink = this._option.vertialShrink;
const layShrink = this._option.layerShrink;
const remarks: [string, string][] = [];
for (let re of this._option.remarks)
if (re[0] && re[1])
{
remarks.push([...re]);
}
let layers: Board[] = [];
let vertials: Board[] = [];
for (let pl of pls)
{
let size = pl.__CacheSize__ as Vector3;
let x = FixDigits(size.x);
let y = FixDigits(size.y);
if (x < 10 || y < 10)
{
console.log("奇怪的矩形");
continue;
}
let box = pl.__CacheBox__;
let minp = box.min.clone();
let ocs: Matrix4;
if (pl.TempData)
{
ocs = pl.TempData.OCS.clone();
minp.applyMatrix4(pl.TempData.OCS);
}
let br: Board;
let mtx = new Matrix4().makeBasis(XAxis, ZAxis.clone().negate(), YAxis);
let shrink = 0;
if (x > y && y <= maxThickness) //层板
{
br = Board.CreateBoard(x, depth - layShrink, y, BoardType.Layer);
br.BoardProcessOption[EBoardKeyList.BigHole] = FaceDirection.Back;
mtx.setPosition(new Vector3(x));
shrink = layShrink;
[minp.x, minp.y, minp.z] = [minp.x + x, minp.z, minp.y];
layers.push(br);
}
else if (x < y && x <= maxThickness)//立板
{
br = Board.CreateBoard(y, depth - verShrink, x, BoardType.Vertical);
[minp.x, minp.y, minp.z] = [minp.x, minp.z, minp.y];
vertials.push(br);
shrink = verShrink;
}
if (!br) continue;
PlCache.get(pl)?.Erase();
//被旋转的矩形
let mtxInv = new Matrix4().getInverse(mtx);
if (ocs)
br.ApplyMatrix(mtx).ApplyMatrix(ocs).ApplyMatrix(mtxInv);
minp.y = min.y + shrink;
let m = new Matrix4().setPosition(minp);
br.ApplyMatrix(m);
br.ApplyMatrix(spaceOCS);
// app.Database.ModelSpace.Append(br);
br.BoardProcessOption[EBoardKeyList.DrillType] = this._option[EBoardKeyList.DrillType];
br.BoardProcessOption.highDrill = new Array(4).fill(this._option[EBoardKeyList.DrillType]);
br.BoardProcessOption[EBoardKeyList.UpSealed] = this._option[EBoardKeyList.UpSealed];
br.BoardProcessOption[EBoardKeyList.DownSealed] = this._option[EBoardKeyList.DownSealed];
br.BoardProcessOption[EBoardKeyList.LeftSealed] = this._option[EBoardKeyList.LeftSealed];
br.BoardProcessOption[EBoardKeyList.RightSealed] = this._option[EBoardKeyList.RightSealed];
br.BoardProcessOption.remarks = remarks;
if (this.spaceParse.Boards.length > 0)
{
let b = this.spaceParse.Boards[0];
br.BoardProcessOption[EBoardKeyList.RoomName] = b.BoardProcessOption[EBoardKeyList.RoomName];
br.BoardProcessOption[EBoardKeyList.CabinetName] = b.BoardProcessOption[EBoardKeyList.CabinetName];
br.BoardProcessOption[EBoardKeyList.BrMat] = b.BoardProcessOption[EBoardKeyList.BrMat];
br.BoardProcessOption[EBoardKeyList.Color] = b.BoardProcessOption[EBoardKeyList.Color];
br.BoardProcessOption[EBoardKeyList.Mat] = b.BoardProcessOption[EBoardKeyList.Mat];
}
}
for (let br of layers)
{
br.Subtract(vertials);
}
return [...vertials, ...layers];
}
}
const tool = new Rect2BoardTool2();

@ -278,6 +278,10 @@ export namespace CheckoutValid
let val = safeEval(v);
switch (k)
{
case "depthExpr":
if (isNaN(safeEval(v, { L: 1, H: 1, W: 1 })))
return "表达式错误";
return "";
case "sealedUp":
case "sealedDown":
case "sealedLeft":
@ -314,6 +318,8 @@ export namespace CheckoutValid
case "grooveAddLength":
case "grooveAddDepth":
case "grooveAddWidth":
case "vertialShrink":
case "layerShrink":
if (isNaN(val))
return "数值不能为空且必须为数字";
default:

@ -193,4 +193,5 @@ export enum CommandNames
DrawTempByImport = "DRAWTEMPBYIMPORT",
CheckEdge = "CHECKEDGE",
Knife = "KNIFES",//编辑BBS
R2B2 = "RECT2BOARD2",
}

@ -210,6 +210,7 @@ import { BuyMaterial } from './../Add-on/BuyMaterial';
import { Interfere } from './../Add-on/interfere';
import { ShowKinfeManageModal } from './../Add-on/showModal/ShowKnifeManageModal';
import { commandMachine } from './CommandMachine';
import { Rect2Board } from "../Add-on/twoD2threeD/Rect2Board";
export function registerCommand()
{
@ -585,6 +586,8 @@ export function registerCommand()
commandMachine.RegisterCommand(CommandNames.CuttingFace, new CuttingByFace());
commandMachine.RegisterCommand(CommandNames.DrawTempByImport, new DrawTemplateByImport());
commandMachine.RegisterCommand(CommandNames.R2B2, new Rect2Board());
}
export async function RegistCustomCommand()

@ -7,7 +7,7 @@ import { EBoardKeyList } from "../Common/BoardKeyList";
import { ICylMetalsOption, IExtMetalsOption, ICompHardwareOption, EMetalsType, IToplineOption } from "../UI/Components/RightPanel/RightPanelInterface";
import { Curve2RecOption } from "../Add-on/twoD2threeD/Modals/Curve2RecModal";
import { IUpdateBoardInfosOption } from "../UI/Components/Board/UpdateBoardInfointerface";
import { IRec2BrOption } from "../Add-on/twoD2threeD/R2bInterface";
import { IRec2BrOption, IRect2Br2Option } from "../Add-on/twoD2threeD/R2bInterface";
export const DefaultLayerBoardConfig: LayerBoardOption = {
version: 2,
@ -656,3 +656,17 @@ export const DefaultR2bOption: IRec2BrOption = {
footerThickness: 18,
};
Object.freeze(DefaultR2bOption);
export const DefaultR2b2Option: IRect2Br2Option = {
version: 1,
depthExpr: "W",
drillType: "",
sealedDown: "1",
sealedLeft: "1",
sealedRight: "1",
sealedUp: "1",
remarks: Array.from({ length: 12 }, () => ["", ""]),
maxThickness: 20,
layerShrink: 0,
vertialShrink: 0,
};
Object.freeze(DefaultR2b2Option);

@ -49,6 +49,7 @@ export enum BoardModalType
R2WR = "R2WR",
ZX2 = "vmodeling",
ZX3 = "3dmodeling",
R2B2 = "R2B2",
}
export interface BoardModalProps
{

@ -384,6 +384,16 @@ export const CommandList: ICommand[] = [
chName: "矩形变板件",
chDes: "将矩形转换为板件",
},
{
icon: IconEnum.R2b2,
typeId: "hb",
link: "#",
defaultCustom: "R2B2",
command: CommandNames.R2B2,
type: "画板",
chName: "矩形变层板立板",
chDes: "将矩形转换为层板立板",
},
{
icon: IconEnum.Rect2Winerack,
typeId: "hb",

@ -70,6 +70,7 @@ export class TopToolBar extends React.Component<{}, {}>
{ svg: IconEnum.Lattice, title: "格子抽", command: CommandNames.Lattice },
{ svg: IconEnum.Curve2Rec, title: "线条变矩形", command: CommandNames.Curve2Rect },
{ svg: IconEnum.Rec2Br, title: "矩形变板件", command: CommandNames.R2b },
{ svg: IconEnum.R2b2, title: "矩形变层板立板", command: CommandNames.R2B2 },
{ svg: IconEnum.UpdateInfo, title: "根据板名修改属性", command: CommandNames.UpdateBoardInfos },
{ svg: IconEnum.ChangeColorByMat, title: "根据板材修改颜色", command: CommandNames.ChangeColorByMaterial },
{ svg: IconEnum.RestoreColor, title: "恢复板件颜色", command: CommandNames.RestoreColor },

@ -182,4 +182,5 @@ export enum IconEnum
CheckNoHoleBoard = "CHECKNOHOLEBOARD.svg",
CheckDrawHole = "CHECKDRAWHOLE.svg",
EditorBBS = "EDITORBBS.svg",
R2b2 = "R2B2.svg",
}

Loading…
Cancel
Save