!2576 功能:一键检查功能

pull/2645/MERGE
黄诗津 6 months ago committed by ChenX
parent 1f3c7e186a
commit d7ea6ec58c

@ -0,0 +1,139 @@
import { ColorMaterial } from "../../Common/ColorPalette";
import { CheckInterfereTool } from "../../Common/InterfereUtil";
import { safeEval } from "../../Common/eval";
import { ExtrudeHole } from "../../DatabaseServices/3DSolid/ExtrudeHole";
import { SweepSolid } from "../../DatabaseServices/3DSolid/SweepSolid";
import { BoardIsLong, BoardIsShort } from "../../DatabaseServices/BoardLinesReactor";
import { Board } from "../../DatabaseServices/Entity/Board";
import { ExtrudeSolid } from "../../DatabaseServices/Entity/Extrude";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { HardwareCompositeEntity } from "../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { GetSealedBoardContour } from "../../GraphicsSystem/CalcEdgeSealing";
import { FeedingToolPath } from "../../GraphicsSystem/ToolPath/FeedingToolPath";
import { Production } from "../../Production/Product";
import { InterferenceCheck } from "../CheckHoles";
export async function InterfereInspection(selectEnts: (ExtrudeSolid | SweepSolid | HardwareCompositeEntity)[])
{
const checkInterfereTool = new CheckInterfereTool(ColorMaterial.GetConceptualMaterial(1));
const objMap = await checkInterfereTool.Check(selectEnts);
const ents = objMap.map(([_, ens]) => [ens, "板件干涉"]);
return ents;
}
export function MaxSizeBoardInspection(boards: Board[])
{
const brs = boards.filter(br => BoardIsLong(br));
return brs.map(br => [[br], "超长板"]);
}
export function MinSizeBoardInspection(boards: Board[])
{
const brs = boards.filter(br => BoardIsShort(br));
return brs.map(br => [[br], "超短板"]);
}
export function ModelInspection(boards: Board[])
{
boards = boards.flatMap(br => br.SplitBoards);
let feedingTool = FeedingToolPath.GetInstance();
let errGrooves: ExtrudeSolid[] = [];
let errHoles: ExtrudeHole[] = [];
for (let br of boards)
{
let errorIndexs = feedingTool.CheckModeling(br);
let grooves = br.Grooves;
for (let index of errorIndexs)
{
errGrooves.push(grooves[index]);
}
errHoles.push(...feedingTool.CheckCustomHole(br));
}
return [...errGrooves.map(g => [[g], "槽错误"]), ...errHoles.map(h => [[h], "孔错误"])];
}
export function SpecialBoardContourInspection(boards: Board[])
{
boards = boards.flatMap(br => br.SplitBoards);
const brs = [];
for (const br of boards)
{
let c = br.ContourCurve;
if (c instanceof Polyline && c.IsIntersectSelf())
{
brs.push([[br], "板件可能存在轮廓自交"]);
}
else
{
let sealedData = GetSealedBoardContour(br);
if (!sealedData)
{
brs.push([[br], "板件可能存在轮廓自交"]);
}
else if (sealedData.hasSealedErr)
{
brs.push([[br], "板封边异常"]);
}
}
}
return brs;
}
export function SplitBoardInspection(boards: Board[])
{
const brs = boards.filter((br: Board) =>
br.BoardProcessOption.spliteHeight
|| br.BoardProcessOption.spliteWidth
|| br.BoardProcessOption.spliteThickness);
return brs.map(br =>
{
const [L, W, H] = [br.Height, br.Width, br.Thickness];
let str = "存在";
if (br.BoardProcessOption.spliteHeight)
{
str += "拆单高(" + safeEval(br.BoardProcessOption.spliteHeight, { L, W, H }, 'L') + "); ";
}
if (br.BoardProcessOption.spliteWidth)
{
str += "拆单宽(" + safeEval(br.BoardProcessOption.spliteWidth, { L, W, H }, 'W') + "); ";
}
if (br.BoardProcessOption.spliteThickness)
{
str += "拆单厚(" + safeEval(br.BoardProcessOption.spliteThickness, { L, W, H }, 'H') + "); ";
}
return [[br], str];
});
}
export async function DrillInspection(boards: Board[])
{
const brs = [];
let res = await InterferenceCheck(boards);
for (const collsionBr of res)
{
brs.push([[collsionBr.LocalBoard, collsionBr.InterBoard], "排钻干涉"]);
}
return brs;
}
export function DrawHoleInspection(boards: Board[])
{
const brs = [];
for (let br of boards)
{
let sealedData = GetSealedBoardContour(br);
if (!sealedData) continue;
let { brContour: outline, sealedContour } = sealedData;
let offsetTanslation = outline.BoundingBox.min;
let info = Production.GetBoardHolesData(br, offsetTanslation, sealedContour);
if (info.frontBackHoles.length === 0 && info.sideHoles.length === 0)
brs.push(br);
}
return brs.map(br => [[br], "没有排孔的板"]);
}

@ -0,0 +1,120 @@
import { Intent } from "@blueprintjs/core";
import { app } from "../../ApplicationServices/Application";
import { ColorMaterial } from "../../Common/ColorPalette";
import { CheckInterfereTool } from "../../Common/InterfereUtil";
import { SweepSolid } from "../../DatabaseServices/3DSolid/SweepSolid";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Entity } from "../../DatabaseServices/Entity/Entity";
import { ExtrudeSolid } from "../../DatabaseServices/Entity/Extrude";
import { HardwareCompositeEntity } from "../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { Command } from "../../Editor/CommandMachine";
import { PromptStatus } from "../../Editor/PromptResult";
import { ModalState } from "../../UI/Components/Modal/ModalInterface";
import { AppToaster } from "../../UI/Components/Toaster";
import { DrawHoleInspection, DrillInspection, InterfereInspection, MaxSizeBoardInspection, MinSizeBoardInspection, ModelInspection, SpecialBoardContourInspection, SplitBoardInspection } from "./Inspection";
import { OneClickInspectionComponent } from "./OneClickInspectionComponent";
import { oneClickInspectionStore } from "./OneClickInspectionStore";
import { ViewInspection } from "./ViewInspection";
export class OneClickInspection implements Command
{
checkInterfereTool: CheckInterfereTool;
async exec()
{
const errEntInfos = new Map<string, (string | Entity[])[][]>();
const store = oneClickInspectionStore;
app.Editor.ModalManage.RenderModal(OneClickInspectionComponent, { store });
const res = await app.Editor.ModalManage.Wait();
if (res.Status === ModalState.Ok)
{
this.checkInterfereTool = new CheckInterfereTool(ColorMaterial.GetConceptualMaterial(1));
let enRes = await app.Editor.GetSelection({
Msg: "选择需要检查的对象",
Filter: { filterTypes: [Entity] }
});
if (enRes.Status !== PromptStatus.OK) return;
let ens = enRes.SelectSet.SelectEntityList;
const parseEntity = (ents: Entity[]) =>
{
const boards = [];
const hardwareCompositeEntitys = [];
const extrudeSolids = [];
const sweepSoilds = [];
for (const ent of ents)
{
if (ent instanceof ExtrudeSolid)
extrudeSolids.push(ent);
if (ent instanceof Board)
boards.push(ent);
else if (ent instanceof HardwareCompositeEntity)
hardwareCompositeEntitys.push(ent);
else if (ent instanceof SweepSolid)
sweepSoilds.push(ent);
}
return { boards, hardwareCompositeEntitys, extrudeSolids, sweepSoilds };
};
let { boards, hardwareCompositeEntitys, extrudeSolids, sweepSoilds } = parseEntity(ens);
const InspectionOption = store.m_Option.InspectionOption;
if (InspectionOption.isMaxSizeBoard)
{
const res = MaxSizeBoardInspection(boards);
errEntInfos.set("超长板", res);
}
if (InspectionOption.isMinSizeBoard)
{
const res = MinSizeBoardInspection(boards);
errEntInfos.set("超短板", res);
}
if (InspectionOption.isModel)
{
const res = ModelInspection(boards);
errEntInfos.set("造型槽错误", res);
}
if (InspectionOption.isSpecialBoardContour)
{
const res = SpecialBoardContourInspection(boards);
errEntInfos.set("异形轮廓错误", res);
}
if (InspectionOption.isInterfere)
{
const res = await InterfereInspection([...hardwareCompositeEntitys, ...extrudeSolids, ...sweepSoilds]);
errEntInfos.set("干涉", res);
}
if (InspectionOption.isDrill)
{
const res = await DrillInspection(boards);
errEntInfos.set("排钻碰撞", res);
}
if (InspectionOption.isSplitBoard)
{
const res = SplitBoardInspection(boards);
errEntInfos.set("有拆单尺寸的板", res);
}
if (InspectionOption.isDrawHole)
{
const res = DrawHoleInspection(boards);
errEntInfos.set("没有排孔的板", res);
}
if ([...errEntInfos.values()].every(v => v.length === 0))
{
AppToaster.show({
message: "恭喜! 没有问题!",
timeout: 5000,
intent: Intent.SUCCESS,
});
}
app.Editor.ModalManage.RenderModeless(ViewInspection, { errEntInfos });
}
}
}

@ -0,0 +1,114 @@
import { Button, Card, Checkbox, Intent } from "@blueprintjs/core";
import { observer } from "mobx-react";
import React, { useEffect, useState } from "react";
import { app } from "../../ApplicationServices/Application";
import { BoardModalType } from "../../UI/Components/Board/BoardModalType";
import { Config_ModalType } from "../../UI/Components/Board/UserConfigComponent";
import { CommonModal } from "../../UI/Components/Modal/ModalContainer";
import { ModalState } from "../../UI/Components/Modal/ModalInterface";
import { AppToaster } from "../../UI/Components/Toaster";
import { OneClickInspectionStore } from "./OneClickInspectionStore";
export const OneClickInspectionComponent = (observer(({ store }: { store: OneClickInspectionStore; }) =>
{
const [inspectionOpt, setInspectionOpt] = useState([
{ name: "超长板检查", key: "isMaxSizeBoard", checked: false, },
{ name: "超短板检查", key: "isMinSizeBoard", checked: false, },
{ name: "造型检查", key: "isModel", checked: false, },
{ name: "异形轮廓错误检查", key: "isSpecialBoardContour", checked: false, },
{ name: "干涉检查", key: "isInterfere", checked: false, },
{ name: "排钻碰撞检查", key: "isDrill", checked: false, },
{ name: "没有排孔的板", key: "isDrawHole", checked: false, },
{ name: "拆单尺寸的板", key: "isSplitBoard", checked: false, },
]);
const [selectAll, setSelectAll] = useState(false);
const inspectionOption = store.m_Option.InspectionOption;
useEffect(() =>
{
const newOpt = inspectionOpt.map((opt) => { return { ...opt, checked: inspectionOption[opt.key] }; });
setInspectionOpt(newOpt);
setSelectAll(newOpt.every(opt => opt.checked));
}, [inspectionOption]);
return (
<CommonModal
title="一键检查"
className="one-click-inspection"
store={store}
configType={Config_ModalType.ConfigListTagModal}
type={BoardModalType.OneClickInspection}
close={() => { app.Editor.ModalManage.Destory(); }}
footerChildren={
<>
<Button
text="确定"
intent={Intent.SUCCESS}
onClick={() =>
{
let error = store.HasInvailValue();
if (error)
{
AppToaster.show({
message: error,
intent: Intent.WARNING,
timeout: 3000,
});
return;
}
app.Editor.ModalManage.m_PromisRes({ Status: ModalState.Ok });
app.Editor.ModalManage.Destory();
}}
/>
<Button
text="取消"
intent={Intent.DANGER}
onClick={() => { app.Editor.ModalManage.Destory(); }}
/>
</>
}
>
<Card style={{ padding: 20, minWidth: 200, minHeight: 300 }}>
<div>
{
inspectionOpt.map((option) =>
{
return (
<Checkbox
key={option.key}
checked={option.checked}
label={option.name}
onChange={() =>
{
const newOpt = inspectionOpt.map(opt => opt.key === option.key ? { ...opt, checked: !option.checked } : opt);
setInspectionOpt(newOpt);
option.checked = !option.checked;
inspectionOption[option.key] = option.checked;
setSelectAll(newOpt.every(opt => opt.checked));
}}
/>
);
})
}
</div>
<Checkbox
checked={selectAll}
label={"全选"}
onChange={() =>
{
setSelectAll(!selectAll);
setInspectionOpt(inspectionOpt.map(option => { return { ...option, checked: !selectAll, }; }));
for (const opt of inspectionOpt)
{
inspectionOption[opt.key] = !selectAll;
}
}}
/>
</Card>
</CommonModal>
);
}));

@ -0,0 +1,42 @@
import { observable, toJS } from "mobx";
import { Singleton } from "../../Common/Singleton";
import { DefaultOneClickInspectionOption } from "../../Editor/DefaultConfig";
import { IConfigOption } from "../../UI/Components/Board/UserConfigComponent";
import { IConfigStore } from "../../UI/Store/BoardStore";
import { OneClickInspectionOption } from "../../UI/Store/OptionInterface/IOptionInterface";
export class OneClickInspectionStore extends Singleton implements IConfigStore
{
@observable configName = "默认";
@observable m_Option: OneClickInspectionOption = DefaultOneClickInspectionOption;
@observable configsNames: string[] = [];
InitOption()
{
Object.assign(this.m_Option, DefaultOneClickInspectionOption);
}
UpdateOption(cof: IConfigOption<OneClickInspectionOption>)
{
Object.assign(this.m_Option, cof.option);
}
SaveConfig()
{
//新的配置
let newConfig: IConfigOption<OneClickInspectionOption> = {};
newConfig.option = toJS(this.m_Option);
return newConfig;
};
HasInvailValue()
{
let flag = "";
if (Object.values(this.m_Option.InspectionOption).every(v => !v))
{
flag = "请选择至少一个选项";
}
return flag;
}
}
export const oneClickInspectionStore = OneClickInspectionStore.GetInstance() as OneClickInspectionStore;

@ -0,0 +1,127 @@
import { Button, Card, Intent, Tab, Tabs } from "@blueprintjs/core";
import React from "react";
import { app } from "../../ApplicationServices/Application";
import { Board } from "../../DatabaseServices/Entity/Board";
import { Entity } from "../../DatabaseServices/Entity/Entity";
import { ExtrudeSolid } from "../../DatabaseServices/Entity/Extrude";
import { HardwareCompositeEntity } from "../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { CommonModal } from "../../UI/Components/Modal/ModalContainer";
export function ViewInspection({ errEntInfos }: { errEntInfos: Map<string, (string | Entity[])[][]>; })
{
const getEntName = (ents: Entity[]) =>
{
let name = "";
for (let i = 0; i < ents.length; i++)
{
const ent = ents[i];
if (i > 0) name += "_";
if (ent instanceof Board)
name += ent.Name;
else if (ent instanceof HardwareCompositeEntity)
name += ent.HardwareOption.name;
else if (ent instanceof ExtrudeSolid)
name += "拉伸实体";
else
name += "实体";
}
return name;
};
const RenderEntityInfo = ({ entityInfo }: { entityInfo: (string | Entity[])[][]; }) =>
{
return (
<div
style={{
overflow: "scroll",
height: 427
}}>
{
entityInfo.map(([ents, msg]: (string | Entity[])[], i) =>
{
const entitys = ents as Entity[];
return (
<div
style={{
display: "flex",
border: "1px solid #ccc",
alignItems: "center",
justifyContent: "space-between",
padding: 3
}}>
<div style={{ width: 25 }}>{(i + 1) + "."}</div>
<div style={{ width: 150 }}>{getEntName(entitys)}</div>
<div style={{ flex: 1 }}>{msg}</div>
<Button
text="定位"
intent={Intent.PRIMARY}
style={{ width: 60 }}
onClick={() =>
{
app.Editor.SetSelection(entitys);
app.Viewer.ZoomtoEntitys(entitys);
}}
/>
</div>
);
})
}
</div>
);
};
return (
<CommonModal
title="一键检查"
className="one-click-inspection"
close={() => { app.Editor.ModalManage.Destory(); }}
hasFooter={false}
>
<Card
style={{
margin: 20,
minWidth: 500,
height: 500
}}>
<div>
<Tabs
id="ViewInspection"
className="view_inspection"
>
{
[...errEntInfos.entries()].map(([key, ents]) =>
{
const count = ents.length;
return <Tab
key={key}
id={key}
title={
<div>
{key} <span style={{ color: count ? "red" : "green" }}>{"(" + count + ")"}</span>
</div>
}
panel={
count ?
<RenderEntityInfo entityInfo={ents} /> :
<div
style={{
borderTop: "1px solid #ccc",
color: "green",
fontWeight: "bold",
paddingTop: 5
}}>
</div>
}
/>;
})
}
</Tabs>
</div>
</Card>
</CommonModal>
);
}

@ -306,6 +306,7 @@ export enum CommandNames
CleanCustomNumber = "CLEANCUSTOMNUMBER",//清除自定义编号
Knife = "KNIFES",//刀具管理
ModifyGroovesKnife = "MODIFYGROOVESKNIFE",//修改凹槽加长 宽 深 刀半径
OneClickInspection = "ONECLICKINSPECTION",//一键检查
R2B2 = "RECT2BOARD2",
FixIntSelfContour = "FIXINTSELFCONTOUR",
ParseHinge = "PARSEHINGE",//分析门板的铰链

@ -212,6 +212,7 @@ import { ShowEditorBBS } from "../Add-on/showModal/ShowModal";
// import { DrawFloor } from '../Add-on/DrawFloor';
// import { RevTarget, SaveTarget } from '../Add-on/RenderTarget';
import { Command_DrawArcBoard } from "../Add-on/ArcBoard/DrawArcBoard";
import { OneClickInspection } from "../Add-on/BoardInspection/OneClickInspection";
import { ImportCFData } from "../Add-on/CF/Import/CFImport";
import { ChangeColorByRoomCabinet } from "../Add-on/ChangeColorByRoomOrCabinet/ChangeColorByRoomOrCabinet";
import { Command_RemovePolylineRepeatPos } from "../Add-on/Cmd_RemovePolylineRepeatPos";
@ -832,6 +833,7 @@ export function registerCommand()
commandMachine.RegisterCommand(CommandNames.FindModelKnifeRadius, new FindModeingKnifeRadius());
commandMachine.RegisterCommand(CommandNames.EditorBBS, new ShowEditorBBS());
commandMachine.RegisterCommand(CommandNames.ToggleDrillingReactor, new ToggleDrillingReactor());
commandMachine.RegisterCommand(CommandNames.OneClickInspection, new OneClickInspection());
commandMachine.RegisterCommand(CommandNames.AddAloneDrillLock, new AddAloneDrillLock(true));
commandMachine.RegisterCommand(CommandNames.RemoveAloneDrillLock, new AddAloneDrillLock(false));

@ -16,7 +16,7 @@ import { CurtailType, IBoardBatchCurtailOption } from "../UI/Store/OptionInterfa
import { BoardProcessOption } from "../UI/Store/OptionInterface/BoardProcessOption";
import { BulkheadCeilingOption } from "../UI/Store/OptionInterface/BulkheadCeilingOption";
import { ClosingStripOption, StripType } from "../UI/Store/OptionInterface/ClosingStripOption";
import { BehindBoardOption, BoardConfigOption, ChangeColorByBoardMaterialOption, ChangeColorByRoomOrCabinetOption, CommonPanelConfigOption, DatalistConfigOption, DoorRelatesInfoOption, IBatchModifyPanelOption, IDimStyleOption, LayerBoardOption, LayerNailOption, ModifyTextsConfigOption, RightPlaneLightOption, ShareBoardInfConfigurationOption, SideBoardOption, SingleBoardOption, TBBoardOption, VerticalBoardOption, WindowPanelConfigOption } from "../UI/Store/OptionInterface/IOptionInterface";
import { BehindBoardOption, BoardConfigOption, ChangeColorByBoardMaterialOption, ChangeColorByRoomOrCabinetOption, CommonPanelConfigOption, DatalistConfigOption, DoorRelatesInfoOption, IBatchModifyPanelOption, IDimStyleOption, LayerBoardOption, LayerNailOption, ModifyTextsConfigOption, OneClickInspectionOption, RightPlaneLightOption, ShareBoardInfConfigurationOption, SideBoardOption, SingleBoardOption, TBBoardOption, VerticalBoardOption, WindowPanelConfigOption } from "../UI/Store/OptionInterface/IOptionInterface";
import { PointLightOption, RectAreaLightOption, SpotLightOption } from "../UI/Store/OptionInterface/LightConfigOption";
import { BehindHeightPositon, RadioType, ViewDirection, ViewportPosition } from "../UI/Store/OptionInterface/OptionEnum";
import { Viewport2ConfigOption, Viewport3ConfigOption, Viewport4ConfigOption, ViewportConfigOption } from "../UI/Store/OptionInterface/ViewportConfigOption";
@ -1061,3 +1061,17 @@ export const DefaultFastDimOption: IFastDimOption = {
filterAppointForBoardNameValues: "",
conditionType: ForBoardNameType.Same,
};
export const DefaultOneClickInspectionOption: OneClickInspectionOption = {
version: 1,
InspectionOption: {
isInterfere: true,
isMaxSizeBoard: true,
isMinSizeBoard: true,
isModel: true,
isDrill: true,
isSpecialBoardContour: true,
isSplitBoard: true,
isDrawHole: true,
}
};
Object.freeze(DefaultOneClickInspectionOption);

@ -313,6 +313,7 @@ export interface BrSealedData
brCurves: Curve[];//封边轮廓(高级封边 已经成组)
highSeals: IHighSealedItem[];//高级封边(一一对应)
hasSealedErr?: boolean;//调用 GetSealedBoardContour 方法时判断是否有出现封边异常
}
class OffsetPolyline2 extends OffsetPolyline
@ -486,9 +487,11 @@ export function GetSealedBoardContour(br: Board): BrSealedData | undefined
sealedContours = polylineOffset.Do();
}
let hasSealedErr = false;
//如果有多个 取最大
if (sealedContours.length > 1)
{
hasSealedErr = true;
Toaster({
message: `有板计算封边异常,请检查!(点击左下角提示可以查看该板)`,
timeout: 15000,
@ -525,6 +528,7 @@ export function GetSealedBoardContour(br: Board): BrSealedData | undefined
sealedContour,
brCurves: curves,
highSeals,
hasSealedErr
};
return res;

@ -58,6 +58,7 @@ export enum BoardModalType
BulkheadCeiling = "BulkheadCeiling",//吊顶轮廓
BulkheadCeilingContour = "BulkheadCeilingContour",//吊顶轮廓
HeadCeilingProfileMaterial = "HeadCeilingProfileMaterial",//吊顶截面材质
OneClickInspection = "OneClickInspection",//一键检查
//独立配置,只存在一个的配置
AutoHoleFaceSetting = "AutoHoleFaceSetting",

@ -55,4 +55,5 @@ export const ConfigCommandMap: { [key in BoardModalType]?: string; } =
curtail: CommandNames.BoardBatchCurtail, //批量内缩
BatchModifyPanel: CommandNames.BatchModifyPanel, //批量修改板件
BoardInfoDim: CommandNames.BoardInfoDim, //板件信息标注
OneClickInspection: CommandNames.OneClickInspection, //一键检查
};

@ -106,6 +106,7 @@ export class TopToolBar extends React.Component<{}, {}>
{ svg: IconEnum.BoardFindModify, title: "批量修改板件大小", command: CommandNames.BatchModifyPanel },
{ svg: IconEnum.ClearRelatedGroove, title: "清除关联切割", command: CommandNames.ClearRef },
{ svg: IconEnum.ModifyGroovesKnife, title: "修改凹槽", command: CommandNames.ModifyGroovesKnife },
{ svg: "", title: "一键检查", command: CommandNames.OneClickInspection },
];
store.iconList.dim = [
{ svg: IconEnum.DAL, title: "对齐标注", command: CommandNames.AlignDim },

@ -351,3 +351,17 @@ export interface IAutoHoleFaceOption extends IBaseOption
hight: number;
filterDrill: string; //被过滤的排钻
}
export interface OneClickInspectionOption extends IBaseOption
{
InspectionOption: {
isInterfere: boolean,
isMaxSizeBoard: boolean,
isMinSizeBoard: boolean,
isModel: boolean,
isDrill: boolean,
isSpecialBoardContour: boolean,
isSplitBoard: boolean,
isDrawHole: boolean,
};
}

Loading…
Cancel
Save