!2522 功能:晨丰开放导入功能

pull/2538/MERGE
黄诗津 7 months ago committed by ChenX
parent 0bbe34e0b4
commit 9a75fbbe77

@ -0,0 +1,246 @@
{
"ModelSpace": [
{
"Name": "层板",
"Type": "Board",
"ColorIndex": 2,
"RoomName": "板主卧",
"CabinetName": "板标准柜",
"Rot": [
90,
0,
0
],
"Pos": [
20,
0,
0
],
"ContourCurve": [
{
"pt": [
0,
0
],
"bul": 0
},
{
"pt": [
0,
100
],
"bul": 0
},
{
"pt": [
80,
100
],
"bul": 0
},
{
"pt": [
80,
0
],
"bul": 0
},
{
"pt": [
0,
0
],
"bul": 0
}
],
"Thickness": 18,
"BrMatName": "默认板材5厘",
"Matrial": "生态板",
"Color": "经典檀木",
"BrType": 1,
"PositionType": 0,
"OpenDir": 0,
"Lines": 0,
"BigHole": 0,
"ComposingFace": 2,
"UpSealed": "1.5",
"DownSealed": "1.5",
"LeftSealed": "1.5",
"RightSealed": "1.5",
"EachEdgeDrills": [
"三合一",
"三合一",
"三合一",
"三合一"
],
"Remarks": [
[
"备注1",
"434"
],
[
"备注2",
"434"
]
],
"Holes": [
{
"Type": "ExtrudeSolid",
"ColorIndex": 2,
"Pos": [
10,
0,
0
],
"ContourCurve": [
{
"pt": [
0,
0
],
"bul": 0
},
{
"pt": [
0,
20
],
"bul": 0
},
{
"pt": [
10,
20
],
"bul": 0
},
{
"pt": [
10,
0
],
"bul": 0
}
]
}
],
"GroovesAddLength": 0,
"GroovesAddWidth": 0,
"GroovesAddDepth": 0,
"KnifeRadius": 3
},
{
"Type": "Hardware",
"BoxSize": [
50,
30,
60
],
"RoomName": "五金主卧",
"CabinetName": "五金标准柜",
"Name": "五金",
"Unit": "个",
"ActualExpr": "L*W*H",
"Model": "X-1",
"Factory": "厂家晨丰",
"Brand": "品牌晨丰",
"Spec": "{L*2}",
"Comments": "五金备注",
"IsHole": true,
"Material": "五金材质",
"Color": "五金颜色"
},
{
"Type": "Topline",
"BoxSize": [
50,
30,
60
],
"RoomName": "顶线主卧",
"CabinetName": "顶线标准柜",
"Name": "顶线",
"Unit": "个",
"ActualExpr": "L*W*H",
"Model": "X-1",
"Factory": "厂家晨丰",
"Brand": "品牌晨丰",
"Spec": "{L*2}",
"Comments": "顶线备注",
"Contour": [
{
"pt": [
0,
0
],
"bul": 0
},
{
"pt": [
0,
20
],
"bul": 0
},
{
"pt": [
20,
20
],
"bul": 0
},
{
"pt": [
20,
0
],
"bul": 0
},
{
"pt": [
0,
0
],
"bul": 0
}
],
"PathCurve": [
{
"pt": [
0,
0
],
"bul": 0
},
{
"pt": [
0,
100
],
"bul": 0
},
{
"pt": [
100,
100
],
"bul": 0
},
{
"pt": [
100,
0
],
"bul": 0
},
{
"pt": [
0,
0
],
"bul": 0
}
]
}
]
}

@ -0,0 +1,314 @@
import { ParseCFDoc } from "../../src/Add-on/CF/Import/CFImport";
import { CFBoard, CFDoc, CFEntityTree, CFHardware, CFTemplate, CFTopline } from "../../src/Add-on/CF/Import/CFInterface";
import { ParseBoard } from "../../src/Add-on/CF/Parse/ParseBoard";
import { ParseAddEntity, ParseEntityTree } from "../../src/Add-on/CF/Parse/ParseEntityTree";
import { ParseTemplate } from "../../src/Add-on/CF/Parse/ParseHardwareAndTemplate";
import { ParseHardwareInfo, ParseTemplateInfo, ParseToplineInfo } from "../../src/Add-on/CF/Parse/ParseHardwareAndTemplateInfo";
import { CADFiler } from "../../src/DatabaseServices/CADFiler";
import { Database } from "../../src/DatabaseServices/Database";
import { Board } from "../../src/DatabaseServices/Entity/Board";
import { BoardType } from "../../src/DatabaseServices/Entity/BoardInterface";
import { Entity } from "../../src/DatabaseServices/Entity/Entity";
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import { HardwareCompositeEntity } from "../../src/DatabaseServices/Hardware/HardwareCompositeEntity";
import { HardwareTopline } from "../../src/DatabaseServices/Hardware/HardwareTopline";
import { TemplateRecord } from "../../src/DatabaseServices/Template/TemplateRecord";
const testBr: CFBoard = {
Name: "层板",
Type: "Board",
ColorIndex: 2,
RoomName: "板主卧",
CabinetName: "板标准柜",
Rot: [90, 0, 0],
Pos: [20, 0, 0],
ContourCurve: [
{ pt: [0, 0], bul: 0 },
{ pt: [0, 100], bul: 0 },
{ pt: [80, 100], bul: 0 },
{ pt: [80, 0], bul: 0 },
{ pt: [0, 0], bul: 0 }
],
Thickness: 18,
BrMatName: "默认板材5厘",
Matrial: "生态板",
Color: "经典檀木",
BrType: 1,
PositionType: 0,
OpenDir: 0,
Lines: 0,
BigHole: 0,
ComposingFace: 2,
UpSealed: "1.5",
DownSealed: "1.5",
LeftSealed: "1.5",
RightSealed: "1.5",
EachEdgeDrills: ["三合一", "三合一", "三合一", "三合一"],
Remarks: [["备注1", "434"], ["备注2", "434"]],
Holes: [
{
Type: "ExtrudeSolid",
ColorIndex: 2,
Pos: [10, 0, 0],
ContourCurve: [
{ pt: [0, 0], bul: 0 },
{ pt: [0, 20], bul: 0 },
{ pt: [10, 20], bul: 0 },
{ pt: [10, 0], bul: 0 },
]
}],
GroovesAddLength: 0,
GroovesAddWidth: 0,
GroovesAddDepth: 0,
KnifeRadius: 3,
};
const testBr2 = Object.assign({}, testBr);
testBr2.Pos = [150, 0, 0];
const testBr3 = Object.assign({}, testBr);
testBr2.Pos = [300, 0, 0];
const entityTree2: CFEntityTree = {
Type: "EntityTree",
Name: "实体2",
Entitys: [
testBr3
],
};
const entityTree: CFEntityTree = {
Type: "EntityTree",
Name: "实体1",
Childen: [
entityTree2,
],
Entitys: [
testBr2
]
};
const testTemp: CFTemplate = {
Type: "Template",
TempalteId: "88888888",
BoxSize: [300, 100, 500],
RoomName: "模板主卧",
CabinetName: "模板标准柜",
Rot: [90, 0, 0],
Pos: [400, 0, 0],
ParamMap: [
{
name: "CZ",
value: "1137"
},
{
name: "QT",
value: "123"
}
]
};
const testHardware: CFHardware = {
Type: "Hardware",
BoxSize: [50, 30, 60],
RoomName: "五金主卧",
CabinetName: "五金标准柜",
Name: "五金",
Unit: "个",
ActualExpr: "L*W*H",
Model: "X-1",
Factory: "厂家晨丰",
Brand: "品牌晨丰",
Spec: "{L*2}",
Comments: "五金备注",
IsHole: true,
Material: "五金材质",
Color: "五金颜色",
};
const testHardware2 = Object.assign({}, testHardware);
testHardware2.HardwarerId = "1111111";
const testTopline: CFTopline = {
Type: "Topline",
BoxSize: [50, 30, 60],
RoomName: "顶线主卧",
CabinetName: "顶线标准柜",
Name: "顶线",
Unit: "个",
ActualExpr: "L*W*H",
Model: "X-1",
Factory: "厂家晨丰",
Brand: "品牌晨丰",
Spec: "{L*2}",
Comments: "顶线备注",
Contour: [
{ pt: [0, 0], bul: 0 },
{ pt: [0, 20], bul: 0 },
{ pt: [20, 20], bul: 0 },
{ pt: [20, 0], bul: 0 },
{ pt: [0, 0], bul: 0 },
],
PathCurve: [
{ pt: [0, 0], bul: 0 },
{ pt: [0, 100], bul: 0 },
{ pt: [100, 100], bul: 0 },
{ pt: [100, 0], bul: 0 },
{ pt: [0, 0], bul: 0 },
],
};
const testTopline2 = Object.assign({}, testTopline);
testTopline2.ToplineId = "222222";
jest.mock("../../src/Add-on/CF/Parse/ParseHardwareAndTemplate", () =>
{
return {
__esModule: true,
ParseTemplate: async (testTemp: CFTemplate, cuDb: Database) =>
{
const newTemp = TestTemplate(cuDb);
await ParseTemplateInfo(newTemp, testTemp, cuDb);
return newTemp;
},
ParseHardware: async (testHardware: CFHardware, cuDb: Database) =>
{
let newTemp: TemplateRecord;
if (testHardware.HardwarerId)
{
newTemp = TestTemplate(cuDb);
await ParseTemplateInfo(newTemp, testTemp, cuDb);
}
const hardware = await ParseHardwareInfo(newTemp, testHardware, cuDb);
return hardware;
},
ParseTopline: async (testTopline: CFTopline, cuDb: Database) =>
{
let contour: Polyline;
if (testTopline.ToplineId)
{
contour = new Polyline().Rectangle(10, 10);
}
const topline = await ParseToplineInfo(contour, testTemp, cuDb);
return topline;
}
};
});
jest.mock("../../src/Add-on/CF/Import/CFImport", () =>
{
return {
__esModule: true,
async ParseCFDoc(document: CFDoc, cuDb: Database)
{
for (const model of document.ModelSpace)
{
if (model.Type === "EntityTree")
{
await ParseEntityTree(model as CFEntityTree, cuDb);
}
else
{
await ParseAddEntity(model, cuDb);
}
}
}
};
});
test('晨丰导入板解析', () =>
{
const br = ParseBoard(testBr);
expect(br).toBeInstanceOf(Board);
const file = EntitysOut(br);
expect(file).toMatchSnapshot();
});
test('晨丰导入模板解析', async () =>
{
const cuDb = new Database();
const newTemp = await ParseTemplate(testTemp, cuDb);
expect(newTemp).toBeInstanceOf(TemplateRecord);
const data = cuDb.FileWrite().ToString();
expect(data).toMatchSnapshot();
});
test('晨丰导入五金解析', async () =>
{
const cuDb = new Database();
let newTemp: TemplateRecord;
const hardware = await ParseHardwareInfo(newTemp, testHardware, cuDb) as HardwareCompositeEntity;
expect(hardware).toBeInstanceOf(HardwareCompositeEntity);
const data = EntitysOut(hardware);
expect(data).toMatchSnapshot();
const cuDb2 = new Database();
let newTemp2: TemplateRecord = TestTemplate(cuDb2);
const hardware2 = await ParseHardwareInfo(newTemp2, testHardware2, cuDb2) as TemplateRecord;
expect(hardware2).toBeInstanceOf(TemplateRecord);
const data2 = cuDb2.FileWrite().ToString();
expect(data2).toMatchSnapshot();
});
test('晨丰导入顶线解析', async () =>
{
const cuDb = new Database();
let contour: Polyline;
const topline = await ParseToplineInfo(contour, testTopline, cuDb);
expect(topline).toBeInstanceOf(HardwareTopline);
const data = EntitysOut(topline);
expect(data).toMatchSnapshot();
let contour2 = new Polyline().Rectangle(10, 10);
const topline2 = await ParseToplineInfo(contour2, testTopline2, cuDb);
expect(topline2).toBeInstanceOf(HardwareTopline);
const data2 = EntitysOut(topline2);
expect(data2).toMatchSnapshot();
});
test('晨丰导入实体树解析', async () =>
{
const cuDb = new Database();
const temp = await ParseEntityTree(entityTree, cuDb) as TemplateRecord;
expect(cuDb.TemplateTable.Objects.length).toBe(2);
expect(temp).toBeInstanceOf(TemplateRecord);
expect((temp.Children[0].Object as TemplateRecord).Name).toBe(entityTree.Childen[0].Name);
});
test('晨丰导入CAD解析', async () =>
{
const cuDb = new Database();
let cfDoc = require("./CFDoc.json");
await ParseCFDoc(cfDoc, cuDb);
const data = cuDb.FileWrite().ToString();
expect(data).toMatchSnapshot();
});
function TestTemplate(cuDb: Database): TemplateRecord
{
const newTemp = new TemplateRecord().InitBaseParams();
const board = Board.CreateBoard(100, 100, 100, BoardType.Layer);
const hardware = new HardwareCompositeEntity();
hardware.Entitys.push(board);
cuDb.ModelSpace.Append(hardware);
cuDb.ModelSpace.Append(board);
newTemp.Objects.push(board.Id, hardware.Id);
newTemp.SetParamExpr("CZ", "1137");
newTemp.SetParamExpr("QT", "123");
newTemp.UpdateTemplateTree();
return newTemp;
}
export function EntitysOut(en: Entity, callback?: (en) => void)
{
let vf = new CADFiler();
en.WriteFile(vf);
return JSON.stringify(vf.Data);
}

@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`晨丰导入CAD解析 1`] = `"[11,103,1,2,1,0,0,1,\\"\\",2,2,0,0,3,\\"Board\\",10,2,100,0,1,2,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,20,0,0,1],0,0,1,3,100,80,18,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[0,100],0,[80,100],0,[80,0],0,true,1,3,20,10,1,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[0,20],0,[10,20],0,[10,0],0,true,0,3,0,0,0,0,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,6.123233995736766e-16,10,1],3,0,0,0,0,0,13,1,\\"层板\\",\\"板主卧\\",\\"板标准柜\\",\\"默认板材5厘\\",\\"生态板\\",\\"经典檀木\\",0,0,\\"不排\\",2,0,\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"\\",\\"\\",\\"\\",4,\\"三合一\\",\\"三合一\\",\\"三合一\\",\\"三合一\\",true,true,2,\\"备注1\\",\\"434\\",\\"备注2\\",\\"434\\",0,0,0,0,0,0,0,true,0,0,null,0,0,\\"HardwareCompositeEntity\\",1,10,2,101,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,\\"Board\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,3,30,50,60,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[50,0],0,[50,30],0,[0,30],0,true,0,3,0,0,0,0,0,13,null,\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",0,0,\\"\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,5,\\"五金\\",false,false,\\"五金颜色\\",\\"五金材质\\",\\"五金\\",\\"五金主卧\\",\\"五金标准柜\\",\\"L*W*H*100\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"1\\",\\"五金备注\\",\\"个\\",0,true,0,0,0,\\"HardwareTopline\\",10,2,102,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,\\"\\",1,\\"\\",1,0,\\"0\\",\\"\\",\\"模板主卧\\",\\"模板标准柜\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",0,2,4,0,0,5,0,2,3,0,0,5,0,0,0,0,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,3,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[],\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,1,\\"CreateObjectData\\",1,[],\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,2,\\"CreateObjectData\\",1,[],2,5,0,0,0,1,2,6,0,0,0,1,2,7,0,0,1,\\"\\",2,8,0,0,0,2,9,0,0,0,1,2,10,0,0,1,\\"\\",2,11,0,0,0,0,1,2,12,0,0,5,0,0,null]"`;
exports[`晨丰导入五金解析 1`] = `"[1,10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,\\"Board\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,3,30,50,60,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[50,0],0,[50,30],0,[0,30],0,true,0,3,0,0,0,0,0,13,null,\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",\\"\\",0,0,\\"\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,5,\\"五金\\",false,false,\\"五金颜色\\",\\"五金材质\\",\\"五金\\",\\"五金主卧\\",\\"五金标准柜\\",\\"L*W*H*100\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"1\\",\\"五金备注\\",\\"个\\",0,true,0,0,0]"`;
exports[`晨丰导入五金解析 2`] = `"[11,102,1,2,1,0,0,1,\\"\\",2,2,0,0,2,\\"HardwareCompositeEntity\\",1,10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,1,\\"Board\\",10,2,101,0,1,2,0,[0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,3,100,100,100,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[100,0],0,[100,100],0,[0,100],0,true,0,3,0,0,0,0,0,13,0,\\"层板\\",\\"五金主卧\\",\\"五金标准柜\\",\\"\\",\\"\\",\\"\\",0,0,\\"不排\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,5,\\"五金\\",false,false,\\"五金颜色\\",\\"五金材质\\",\\"五金\\",\\"五金主卧\\",\\"五金标准柜\\",\\"L*W*H*100\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"1\\",\\"五金备注\\",\\"个\\",0,true,0,0,0,\\"Board\\",10,2,101,0,1,2,0,[0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,3,100,100,100,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[100,0],0,[100,100],0,[0,100],0,true,0,3,0,0,0,0,0,13,0,\\"层板\\",\\"五金主卧\\",\\"五金标准柜\\",\\"\\",\\"\\",\\"\\",0,0,\\"不排\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,2,4,0,0,5,0,2,3,0,0,5,0,0,0,0,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,2,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[],\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,1,\\"CreateObjectData\\",1,[],2,5,0,0,0,1,2,6,0,0,0,1,2,7,0,0,1,\\"\\",2,8,0,0,0,2,9,0,0,0,1,2,10,0,0,1,\\"\\",2,11,0,0,0,0,1,2,12,0,0,5,0,0,null]"`;
exports[`晨丰导入板解析 1`] = `"[10,2,0,0,0,2,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,20,0,0,1],0,0,1,3,100,80,18,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[0,100],0,[80,100],0,[80,0],0,true,1,3,20,10,1,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[0,20],0,[10,20],0,[10,0],0,true,0,3,0,0,0,0,0,[0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,1,0,0,0,20,6.123233995736766e-16,10,1],3,0,0,0,0,0,13,1,\\"层板\\",\\"板主卧\\",\\"板标准柜\\",\\"默认板材5厘\\",\\"生态板\\",\\"经典檀木\\",0,0,\\"不排\\",2,0,\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"1.5\\",\\"\\",\\"\\",\\"\\",4,\\"三合一\\",\\"三合一\\",\\"三合一\\",\\"三合一\\",true,true,2,\\"备注1\\",\\"434\\",\\"备注2\\",\\"434\\",0,0,0,0,0,0,0,true,0,0,null,0,0]"`;
exports[`晨丰导入模板解析 1`] = `"[11,102,1,2,1,0,0,1,\\"\\",2,2,0,0,2,\\"HardwareCompositeEntity\\",1,10,2,100,0,1,7,0,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,1,\\"Board\\",10,2,101,0,1,2,0,[0,6.123233995736766e-17,1,0,-1,0,0,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,3,100,100,100,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[100,0],0,[100,100],0,[0,100],0,true,0,3,0,0,0,0,0,13,0,\\"层板\\",\\"模板主卧\\",\\"模板标准柜\\",\\"\\",\\"\\",\\"\\",0,0,\\"不排\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,5,\\"五金\\",false,false,\\"\\",\\"\\",\\"复合实体\\",\\"模板主卧\\",\\"模板标准柜\\",\\"L*W*H*100\\",\\"L*W*H*300\\",\\"X-1\\",\\"晨丰\\",\\"晨丰\\",\\"个\\",\\"1\\",\\"\\",\\"\\",0,true,0,0,0,\\"Board\\",10,2,101,0,1,2,0,[0,6.123233995736766e-17,1,0,-1,0,0,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,[1,0,0,0,0,6.123233995736766e-17,1,0,0,-1,6.123233995736766e-17,0,400,0,0,1],0,0,1,3,100,100,100,true,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[100,0],0,[100,100],0,[0,100],0,true,0,3,0,0,0,0,0,13,0,\\"层板\\",\\"模板主卧\\",\\"模板标准柜\\",\\"\\",\\"\\",\\"\\",0,0,\\"不排\\",2,0,\\"1\\",\\"1\\",\\"1\\",\\"1\\",\\"\\",\\"\\",\\"\\",4,\\"不排\\",\\"不排\\",\\"不排\\",\\"不排\\",true,true,0,0,0,0,0,0,0,0,true,0,0,null,0,0,2,4,0,0,5,0,2,3,0,0,5,0,0,0,0,0,1,0,1,\\"CommandHistoryRecord\\",1,\\"\\",1,2,2,\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,0,\\"CreateObjectData\\",1,[],\\"HistorycRecord\\",2,\\"RemoveObjectData\\",1,1,\\"CreateObjectData\\",1,[],2,5,0,0,0,1,2,6,0,0,0,1,2,7,0,0,1,\\"\\",2,8,0,0,0,2,9,0,0,0,1,2,10,0,0,1,\\"\\",2,11,0,0,0,0,1,2,12,0,0,5,0,0,null]"`;
exports[`晨丰导入顶线解析 1`] = `"[10,2,100,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,5,[0,0],0,[0,20],0,[20,20],0,[20,0],0,[0,0],0,false,1,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,5,[0,0],0,[0,100],0,[100,100],0,[100,0],0,[0,0],0,true,1,0,\\"0\\",\\"顶线\\",\\"顶线主卧\\",\\"顶线标准柜\\",\\"\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"顶线备注\\",0]"`;
exports[`晨丰导入顶线解析 2`] = `"[10,2,101,0,1,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,4,[0,0],0,[10,0],0,[10,10],0,[0,10],0,true,1,\\"Polyline\\",10,2,0,0,0,7,0,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],0,0,1,2,5,[0,0],0,[0,100],0,[100,100],0,[100,0],0,[0,0],0,true,1,0,\\"0\\",\\"顶线\\",\\"顶线主卧\\",\\"顶线标准柜\\",\\"\\",\\"L*W*H\\",\\"X-1\\",\\"厂家晨丰\\",\\"品牌晨丰\\",\\"{L*2}\\",\\"顶线备注\\",0]"`;

@ -7,7 +7,7 @@ export interface MaterialInfo
material: string;
color: string;
}
export class JiaJuLoader
export class BoardMaterialLoader
{
constructor() { }

@ -0,0 +1,117 @@
import { Intent } from "@blueprintjs/core";
import { Box3 } from "three";
import { app } from "../../../ApplicationServices/Application";
import { FS } from "../../../Common/FileSystem";
import { JigMoveEntity } from "../../../Common/JigMove";
import { Database } from "../../../DatabaseServices/Database";
import { Board } from "../../../DatabaseServices/Entity/Board";
import { Entity } from "../../../DatabaseServices/Entity/Entity";
import { HardwareCompositeEntity } from "../../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { Command, CommandWrap } from "../../../Editor/CommandMachine";
import { AppToaster } from "../../../UI/Components/Toaster";
import { CuttingBoardByBoard } from "../../BoardCutting/CuttingUtils2";
import { ParseAddEntity, ParseEntityTree } from "../Parse/ParseEntityTree";
import { BoardMaterialLoader } from "./BoardMaterialLoader";
import { CFDoc, CFEntityTree } from "./CFInterface";
export class ImportCFData implements Command
{
exec()
{
FS.ChooseFile({
filter: ".json", multiple: false, callback: async (files) =>
{
for (let i = 0; i < files.length; i++)
{
let file = files.item(i);
let data = await file.text();
try
{
let doc = JSON.parse(data);
if (doc.ModelSpace)
{
await ParseCFDoc(doc, app.Database);
}
else
{
AppToaster.show({
message: `${file.name}不是有效的晨丰JSON文件!`,
timeout: 5000,
intent: Intent.WARNING,
});
}
}
catch (error)
{
AppToaster.show({
message: `${file.name}导入失败!`,
timeout: 5000,
intent: Intent.WARNING,
});
}
}
}
});
}
}
export async function ParseCFDoc(document: CFDoc, cuDb: Database)
{
await CommandWrap(async () =>
{
const brMatLoader = new BoardMaterialLoader();
await brMatLoader.LoaderMaterialInfo();
const boardMaterialMap = brMatLoader.Code_MaterialInfo;
for (const model of document.ModelSpace)
{
if (model.Type === "EntityTree")
{
await ParseEntityTree(model as CFEntityTree, cuDb, boardMaterialMap);
}
else
{
await ParseAddEntity(model, cuDb, boardMaterialMap);
}
}
let ents = app.CommandReactor._createObejcts.filter(obj => obj instanceof Entity) as Entity[];
let brs = ents.filter(en => en instanceof Board) as Board[];
let hws = ents.filter(en => en instanceof HardwareCompositeEntity).filter(hw => (hw as HardwareCompositeEntity).HardwareOption.isHole) as HardwareCompositeEntity[];
if (ents.length === 0)
return true;
let box = new Box3;
for (let en of ents)
box.union(en.BoundingBox);
app.Editor.GetPointServices.snapServices.FilterEntitys = new Set(ents);
let ok = await JigMoveEntity(ents, box.isEmpty() ? undefined : box.min);
app.Editor.GetPointServices.snapServices.FilterEntitys = undefined;
if (ok)
{
if (brs.length !== 0)
{
app.Editor.Prompt("开始计算薄背板拉槽!");
let bbrs: Board[] = [];
let allBrs: Board[] = [];
for (let br of brs)
{
if (br.IsKnife)//br.BoardType === BoardType.Behind
bbrs.push(br);
else
allBrs.push(br);
}
CuttingBoardByBoard(allBrs, bbrs);
}
//直接调用五金挖孔
await app._hardwareCuttingReactor.StartReactor(hws, new Set);
}
return !ok;
}, "晨丰导入");
}

@ -0,0 +1,206 @@
//通用类型定义
type CurverType = "Curve" | "Polyline" | "Rect" | "Line" | "Arc" | "Circle";
type EntityType = "Entity" | "ExtrudeSolid" | "Board" | "Template" | "EntityTree" | "Hardware" | "Topline";
// ContourCurve 定义轮廓曲线,每个点的坐标和弯曲度,
// pt为点坐标,bul为弯曲度(区间-1~1),俗称弓弦比
// bul为0时为直线,bul为0.5时为半圆,正负为上下弯曲的方向
// bul值为(弧线两点直线的中点到弧线中点的距离)除以(弧线两点直线的中点到弧线起点的距离)
export type PolylineContour = { pt: [number, number], bul: 0; }[]; //多段线轮廓
export type CircleContour = { Radius: number, Center: [number, number, number]; }; //圆形轮廓
type ExtrudeContour = PolylineContour | CircleContour;
//图纸(文档)
export interface CFDoc
{
//定义模型空间,包含所有实体类
ModelSpace: CFEntity[]; //模型空间
// ProcessGroup: any;
}
// 定义实体类,包含所有实体通用属性
export interface CFEntity
{
Type: EntityType | CurverType; //实体类型
Id?: number; //自定义id加工组使用
ColorIndex?: number; //颜色索引 值区间0-255
// 定位方式选择 OCS 或 pos(位置) + rot(旋转) 或 pos(位置) + Qua(四元数)
OCS?: number[]; //OCS矩阵 长度16的数组
//定位方式 pos(位置) rot(旋转)
Pos?: [number, number, number]; //位置
Rot?: [number, number, number]; //欧拉旋转角
// Or
Qua?: [number, number, number, number]; //四元数旋转角
}
export interface CFExtrudeSolid extends CFEntity
{
// Type: "ExtrudeSolid" //类型拉伸实体(必填)
Width?: number; //宽
Height?: number; //高
// Or
ContourCurve?: ExtrudeContour; //轮廓曲线
Thickness?: number; //厚度
GroovesAddLength?: number; //槽加长
GroovesAddWidth?: number; //槽加宽
GroovesAddDepth?: number; //槽加深
KnifeRadius?: number; //刀半径
//孔洞本质上也是拉伸实体,一般孔洞只需要提供位置,轮廓曲线和厚度即可
Holes?: CFExtrudeSolid[]; //孔洞
}
export interface CFBoard extends CFExtrudeSolid
{
// Type: "Board"; //类型板(必填)
Name?: string; //板名称
BrType?: number; //板类型(选填) 0:层板,1:立板,2:背板
//定位类型0-3
PositionType?: number; //定位类型(选填) 0:晨丰基点(默认),1:基于板盒子最小点,2:基于板盒子中心点
OpenDir?: number; //打开方向(选填) 0:非门板(默认),1:左开门板,2:右开门板,3:上开门板,4:下开门板,
//纹路0-2
Lines?: number; //纹路(选填) 0:正纹(默认),1:反,2:可翻转
BigHole?: number; //大孔面(选填) 0:正(默认),1:反
ComposingFace?: number; //排版面(选填) 0:正面,1:背面,2:随意面(默认)
RoomName?: string; //房名
CabinetName?: string; //柜名
BrMatName?: string; //板材名
Matrial?: string; //材料
Color?: string; //颜色
//板材信息可以自定义写入,也可以通过材质编码ID获取对应的值
BoardMaterialId?: string; //板材信息Id
UpSealed?: string; //封边上下左右
DownSealed?: string;
LeftSealed?: string;
RightSealed?: string;
// 封边信息
// 普通板时使用 UpSealed,DownSealed,LeftSealed,RightSealed 表示上下左右封边的值
// 异形板时使用 EachSealeds 数组表示每个边的封边数据,size表示封边的厚度
EachSealeds?: { size: number; }[]; //每个边的封边数据
EachEdgeDrills?: string[]; //每个边的排钻数据
FrontDrill?: boolean; //正排孔面
BackDrill?: boolean; //反排孔面
Remarks?: [string, string][]; //备注
}
export interface CFEntityTree extends CFEntity
{
// Type: "EntityTree"; //类型实体树(必填)
Name?: string; //模板空间名称
Entitys?: CFEntity[]; //实体数组
Childen?: CFEntityTree[]; //子模板数组
}
//模块
export interface CFTemplate extends CFEntity
{
// Type: "Template"; //类型模板(必填)
TempalteId?: string; //模板ID
Name?: string; //模板名称
//模块参数
Lenght?: number; //长度
Width?: number; //宽度
Height?: number; //高度
// Or
BoxSize?: [number, number, number]; //盒子尺寸
ParamMap?: { name: string, value: string; }[]; //模块参数
RoomName?: string; //房名
CabinetName?: string; //柜名
}
export interface CFHardware extends CFTemplate
{
// Type: "Hardware"; //类型五金(必填)
Name?: string; //五金名称
HardwarerId?: string; //五金模板ID
Unit?: string; //单位
ActualExpr?: string; //价格表达式
Model?: string; //型号
Factory?: string; //厂家
Brand?: string; //品牌
Spec?: string; //规格
Comments?: string; //备注
IsHole?: boolean; //是否挖孔
Material?: string; //材质
Color?: string; //颜色
}
export interface CFTopline extends CFTemplate
{
// Type: "Topline"; //类型顶线(必填)
Name?: string; //顶线名称
ToplineId?: string; //顶线横截面轮廓模板ID
Unit?: string; //单位
ActualExpr?: string; //价格表达式
Model?: string; //型号
Factory?: string; //厂家
Brand?: string; //品牌
Spec?: string; //规格
Comments?: string; //备注
Contour?: { pt: [number, number], bul: 0; }[]; //横截面轮廓曲线
PathCurve?: ExtrudeContour; //绘制路径曲线
}
export interface CFCurve extends CFEntity
{
// Type: "Curve"; //类型曲线(必填)
}
export interface CFLine extends CFCurve
{
// Type: "Line"; //类型直线(必填)
StartPoint: [number, number, number]; //起点
EndPoint: [number, number, number]; //终点
}
export interface CFPolyline extends CFCurve
{
// Type: "Polyline"; //类型多段线(必填)
ContourCurve?: { pt: [number, number], bul: 0; }[]; //轮廓曲线
}
export interface CFRect extends CFCurve
{
// Type: "Rect"; //类型矩形(必填)
Width: number; //宽度
Height: number; //高度
}
export interface CFCircle extends CFCurve
{
// Type: "Circle"; //类型圆形(必填)
Radius: number; //半径
Center: [number, number, number]; //中心点
}
// interface CFPRocessGroup
// {
// name: string;
// entitys: [1, 2, 3, 4, 5, 6, 7, 8, 9];
// }

@ -0,0 +1,217 @@
import { Intent, Position, Toaster } from "@blueprintjs/core";
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
import { Log, LogType } from "../../../Common/Log";
import { Board } from "../../../DatabaseServices/Entity/Board";
import { BoardOpenDir, ComposingType, LinesType } from "../../../DatabaseServices/Entity/BoardInterface";
import { ExtrudeContourCurve, ExtrudeSolid } from "../../../DatabaseServices/Entity/Extrude";
import { Polyline } from "../../../DatabaseServices/Entity/Polyline";
import { userConfig } from "../../../Editor/UserConfig";
import { DrillType, FaceDirection } from "../../DrawDrilling/DrillType";
import { BoardType } from "../../Erp/Models/CadBlock";
import { MaterialInfo } from "../Import/BoardMaterialLoader";
import { CFBoard, CircleContour } from "../Import/CFInterface";
import { ParseCurve } from "./ParseCurve";
export function ParseBoard(el: CFBoard, boardMaterialMap?: Map<string, MaterialInfo>)
{
const br = new Board();
br.Name = el.Name ?? "";
br.OpenDir = el.OpenDir ?? BoardOpenDir.None;
const parseCurve = new ParseCurve();
let pl: ExtrudeContourCurve;
if (el.ContourCurve)
{
if ((el.ContourCurve as CircleContour).Center !== undefined)
{
const { Center, Radius } = el.ContourCurve as CircleContour;
pl = parseCurve.ParseCircle(Radius, Center);
}
else
pl = parseCurve.ParsePolyline(el.ContourCurve, true);
}
else if (el.Height && el.Width)
{
pl = parseCurve.ParseRect(el.Height, el.Width);
}
else
{
Toaster.create({
className: "recipe-toaster",
position: Position.TOP,
canEscapeKeyClear: false,
}).show({
message: `无法绘制板${br.Name}轮廓`,
timeout: 5000,
intent: Intent.DANGER,
});
return;
}
br.ContourCurve = pl;
br.Thickness = el.Thickness ?? 1;
if (el.Holes)
{
for (const hole of el.Holes)
{
let pl: Polyline;
if (hole.ContourCurve)
{
pl = parseCurve.ParsePolyline(hole.ContourCurve, true);
}
else if (hole.Height && hole.Width)
{
pl = parseCurve.ParseRect(hole.Height, hole.Width);
}
else
{
Toaster.create({
className: "recipe-toaster",
position: Position.TOP,
canEscapeKeyClear: false,
}).show({
message: `${br.Name}的造型轮廓错误`,
timeout: 5000,
intent: Intent.DANGER,
});
continue;
}
let extrude = new ExtrudeSolid();
extrude.ContourCurve = pl;
extrude.Thickness = hole.Thickness ?? 1;
if (hole.Pos)
extrude.Move(new Vector3(...hole.Pos));
br.Grooves.push(extrude);
}
}
br.GroovesAddLength = el.GroovesAddLength ?? 0;
br.GroovesAddWidth = el.GroovesAddWidth ?? 0;
br.GroovesAddDepth = el.GroovesAddDepth ?? 0;
br.KnifeRadius = el.KnifeRadius ?? 3;
if (el.BrType !== undefined) //默认位置
{
if (el.BrType === BoardType.Layer)
{
br.BoardType = BoardType.Layer;
br.ColorIndex = 2;
}
else if (el.BrType === BoardType.Vertical)
{
br.BoardType = BoardType.Vertical;
br.ColorIndex = 11;
}
else
{
br.BoardType = BoardType.Behind;
br.ColorIndex = 3;
}
}
if (el.PositionType !== undefined)
{
if (el.PositionType === 1) //基于盒子最左下角点
{
if (el.BrType === BoardType.Layer)
br.Move(new Vector3(br.Height, 0, 0));
else if (el.BrType === BoardType.Behind)
br.Move(new Vector3(0, br.Thickness, 0));
}
else if (el.PositionType === 2) //基于盒子中心点
{
if (el.BrType === BoardType.Layer)
br.Move(new Vector3(br.Height / 2, -br.Width / 2, -br.Thickness / 2));
else if (el.BrType === BoardType.Vertical)
br.Move(new Vector3(-br.Thickness / 2, -br.Width / 2, - br.Height / 2));
else
br.Move(new Vector3(-br.Width / 2, br.Thickness / 2, -br.Height / 2));
}
}
if (el.ColorIndex)
br.ColorIndex = el.ColorIndex;
let mtx = new Matrix4();
if (el.OCS)
{
if (el.OCS.length != 16)
Log("OCS数组错误!", LogType.Error);
else
mtx = new Matrix4().fromArray(el.OCS);
}
else
{
const angle = Math.PI / 180;
if (el.Rot)
{
mtx.makeRotationFromEuler(new Euler(el.Rot[0] * angle, el.Rot[1] * angle, el.Rot[2] * angle, "ZYX"));
}
else if (el.Qua)
{
const quaternion = new Quaternion();
quaternion.setFromAxisAngle(new Vector3(el.Qua[0], el.Qua[1], el.Qua[2]), el.Qua[3]);
mtx.makeRotationFromQuaternion(quaternion);
}
if (el.Pos)
{
mtx.setPosition(el.Pos[0], el.Pos[1], el.Pos[2]);
}
}
br.ApplyMatrix(mtx);
const process = br.BoardProcessOption;
process.roomName = el.RoomName ?? "";
process.cabinetName = el.CabinetName ?? "";
process.boardName = el.BrMatName ?? "";
process.material = el.Matrial ?? "";
process.color = el.Color ?? "";
if (el.BoardMaterialId && boardMaterialMap?.size)
{
const materialParam = boardMaterialMap.get(el.BoardMaterialId);
if (materialParam)
{
process.boardName = materialParam.brName;
process.material = materialParam.material;
process.color = materialParam.color;
}
}
process.lines = el.Lines ?? LinesType.CanReversal;
process.bigHoleDir = el.BigHole ?? FaceDirection.Front;
process.composingFace = el.ComposingFace ?? ComposingType.Arbitrary;
process.sealedUp = el.UpSealed ?? "";
process.sealedDown = el.DownSealed ?? "";
process.sealedLeft = el.LeftSealed ?? "";
process.sealedRight = el.RightSealed ?? "";
process.frontDrill = el.FrontDrill ?? true;
process.backDrill = el.BackDrill ?? true;
if (el.EachEdgeDrills)
{
process.highDrill = el.EachEdgeDrills;
let types = ["不排", ...userConfig.DrillConfigs.keys()];
let set = new Set(process.highDrill);
if (set.size > 1)
process.drillType = DrillType.More;
else if (set.size === 1)
process.drillType = (process.highDrill[0] === "不排" ? process.highDrill[0] : types[1]) ?? "不排";
else
process.drillType = DrillType.Invail;
}
else
Log(`板:${br.Name}没有提供排钻信息!`, LogType.Warning, [br]);
if (el.EachSealeds)
process.highSealed = el.EachSealeds;
if (el.Remarks)
process.remarks = el.Remarks;
return br;
}

@ -0,0 +1,44 @@
import { Vector2, Vector3 } from "three";
import { Circle } from "../../../DatabaseServices/Entity/Circle";
import { Line } from "../../../DatabaseServices/Entity/Line";
import { Polyline, PolylineProps } from "../../../DatabaseServices/Entity/Polyline";
export class ParseCurve
{
ParseLine(StartPoint: [number, number, number], EndPoint: [number, number, number])
{
const startPoint = new Vector3().fromArray(StartPoint);
const endPoint = new Vector3().fromArray(EndPoint);
const line = new Line(startPoint, endPoint);
return line;
}
ParsePolyline(ContourCurve, isColosed: boolean = false)
{
const pl = new Polyline();
const paths: PolylineProps[] = ContourCurve.map((path) =>
{
return {
pt: new Vector2().fromArray(path.pt),
bul: path.bul
};
});
pl.LineData = paths;
pl.CloseMark = isColosed;
return pl;
}
ParseRect(Width: number, Height: number)
{
const pl = new Polyline();
pl.Rectangle(Width, Height);
return pl;
}
ParseCircle(Radius: number, Center: [number, number, number])
{
const conter = new Vector3().fromArray(Center);
const cir = new Circle(conter, Radius);
return cir;
}
}

@ -0,0 +1,89 @@
import { Database } from "../../../DatabaseServices/Database";
import { Entity } from "../../../DatabaseServices/Entity/Entity";
import { TemplateRecord } from "../../../DatabaseServices/Template/TemplateRecord";
import { MaterialInfo } from "../Import/BoardMaterialLoader";
import { CFEntity, CFEntityTree } from "../Import/CFInterface";
import { ParseBoard } from "./ParseBoard";
import { ParseHardware, ParseTemplate, ParseTopline } from "./ParseHardwareAndTemplate";
export async function ParseEntityTree(model: CFEntityTree, cuDb: Database, boardMaterialMap?: Map<string, MaterialInfo>): Promise<TemplateRecord | Entity>
{
let entitys: Entity[] = [];
let templates: TemplateRecord[] = [];
if (model.Entitys?.length)
{
for (const entInfo of model.Entitys)
{
let en = await ParseAddEntity(entInfo, cuDb);
if (en)
{
if (en instanceof Entity)
{
entitys.push(en);
}
else if (en instanceof TemplateRecord)
{
templates.push(en);
}
}
}
}
if (model.Childen?.length)
{
for (const m of model.Childen)
{
let temp = await ParseEntityTree(m, cuDb, boardMaterialMap);
if (temp && temp instanceof TemplateRecord)
templates.push(temp);
}
}
if (templates.length > 0 || entitys.length > 0)
{
let template = new TemplateRecord().InitBaseParams();
template.Name = model.Name;
cuDb.TemplateTable.Add(template);
if (entitys.length > 0)
template.Objects.push(...entitys.map(en => en.Id));
if (templates.length > 0)
template.Children.push(...templates.map(t => t.Id));
return template;
}
}
export async function ParseAddEntity(model: CFEntity, cuDb: Database, boardMaterialMap?: Map<string, MaterialInfo>)
{
let en: Entity | TemplateRecord | undefined;
switch (model.Type)
{
case "Board":
en = await ParseBoard(model, boardMaterialMap);
break;
case "Template":
en = await ParseTemplate(model, cuDb);
break;
case "Hardware":
en = await ParseHardware(model, cuDb);
break;
case "Topline":
en = await ParseTopline(model, cuDb);
break;
default:
break;
}
if (en)
{
if (en instanceof Entity)
{
cuDb.ModelSpace.Add(en);
}
else if (en instanceof TemplateRecord)
{
cuDb.TemplateTable.Add(en);
}
}
return en;
}

@ -0,0 +1,118 @@
import { Intent } from "@blueprintjs/core";
import { MaterialUrls, ToplineUrls } from "../../../Common/HostUrl";
import { PostJson, RequestStatus } from "../../../Common/Request";
import { MaterialIn, toplineFileIn } from "../../../Common/SerializeMaterial";
import { DuplicateRecordCloning } from "../../../Common/Status";
import { inflateBase64 } from "../../../Common/inflate";
import { Database } from "../../../DatabaseServices/Database";
import { Polyline } from "../../../DatabaseServices/Entity/Polyline";
import { PhysicalMaterialRecord } from "../../../DatabaseServices/PhysicalMaterialRecord";
import { TemplateParamType } from "../../../DatabaseServices/Template/Param/TemplateParamType";
import { GetOnlineTemplate } from "../../../DatabaseServices/Template/TempateUtils";
import { TemplateRecord } from "../../../DatabaseServices/Template/TemplateRecord";
import { AppToaster } from "../../../UI/Components/Toaster";
import { CFHardware, CFTemplate, CFTopline } from "../Import/CFInterface";
import { ParseHardwareInfo, ParseTemplateInfo, ParseToplineInfo } from "./ParseHardwareAndTemplateInfo";
export async function ParseTemplate(temp: CFTemplate, cuDb: Database)
{
const newTemp = await GetTemplate(temp, cuDb);
if (temp.ParamMap)
{
for (const mk of temp.ParamMap)
{
const param = newTemp.GetParam(mk.name);
if (param && param.type === TemplateParamType.Material)
{
const mat = await LoadMaterial(mk.value.toString(), cuDb);
if (mat)
param.MaterialValue = mat;
}
}
}
await ParseTemplateInfo(newTemp, temp, cuDb);
return newTemp;
}
export async function GetTemplate(temp: CFTemplate, cuDb: Database)
{
let newTemp: TemplateRecord;
if (temp.TempalteId)
{
const template = await GetOnlineTemplate(temp.TempalteId.toString());
if (template)
{
newTemp = cuDb.WblockCloneObejcts([template], cuDb.TemplateTable, new Map(), DuplicateRecordCloning.Ignore)[0] as TemplateRecord;
}
}
return newTemp;
}
export async function ParseHardware(el: CFHardware, cuDb: Database)
{
let newTemp: TemplateRecord;
if (el.HardwarerId)
{
newTemp = await ParseTemplate(el, cuDb);
}
const hardware = await ParseHardwareInfo(newTemp, el, cuDb);
return hardware;
}
export async function ParseTopline(el: CFTopline, cuDb: Database)
{
let contour: Polyline;
if (el.ToplineId)
{
const data = await PostJson(ToplineUrls.detail, { topline_id: el.ToplineId });
if (data.err_code === RequestStatus.Ok)
{
const file = inflateBase64(data.toplines.file);
contour = toplineFileIn(file);
}
}
const topline = await ParseToplineInfo(contour, el, cuDb);
return topline;
}
async function LoadMaterial(fetchMaterialId: string, cuDb: Database): Promise<PhysicalMaterialRecord>
{
let mtl: PhysicalMaterialRecord;
let data = await PostJson(MaterialUrls.detail, { material_id: fetchMaterialId });
if (data.err_code !== RequestStatus.Ok)
{
AppToaster.show({
message: `错误:无法从远程获取到材质数据!id:${fetchMaterialId}`,
timeout: 5000,
intent: Intent.DANGER,
}, "no_mtl_data");
return;
}
try
{
let jsonData = JSON.parse(inflateBase64(data.materials.file));
let mtlOut = MaterialIn(jsonData) as PhysicalMaterialRecord;
mtl = cuDb.WblockCloneObejcts(
[mtlOut],
cuDb.MaterialTable,
new Map(),
DuplicateRecordCloning.Ignore
)[0] as PhysicalMaterialRecord;
return mtl;
}
catch (error)
{
AppToaster.show({
message: `加载材质失败! id:${fetchMaterialId}`,
timeout: 5000,
intent: Intent.WARNING,
});
}
}

@ -0,0 +1,181 @@
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
import { EBoardKeyList } from "../../../Common/BoardKeyList";
import { Log, LogType } from "../../../Common/Log";
import { Database } from "../../../DatabaseServices/Database";
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 { HardwareCompositeEntity } from "../../../DatabaseServices/Hardware/HardwareCompositeEntity";
import { HardwareTopline } from "../../../DatabaseServices/Hardware/HardwareTopline";
import { TemplateParamType } from "../../../DatabaseServices/Template/Param/TemplateParamType";
import { TemplateRecord } from "../../../DatabaseServices/Template/TemplateRecord";
import { CFHardware, CFTemplate, CFTopline, CircleContour } from "../Import/CFInterface";
import { ParseCurve } from "./ParseCurve";
export async function ParseTemplateInfo(newTemp: TemplateRecord, tempInfo: CFTemplate, cuDb: Database)
{
if (newTemp)
{
newTemp.Name = tempInfo.Name;
let mtx = new Matrix4();
if (tempInfo.OCS)
{
if (tempInfo.OCS.length != 16)
Log("OCS数组错误!", LogType.Error);
else
mtx = new Matrix4().fromArray(tempInfo.OCS);
}
else
{
const angle = Math.PI / 180;
if (tempInfo.Rot)
{
mtx.makeRotationFromEuler(new Euler(tempInfo.Rot[0] * angle, tempInfo.Rot[1] * angle, tempInfo.Rot[2] * angle, "ZYX"));
}
else if (tempInfo.Qua)
{
const quaternion = new Quaternion();
quaternion.setFromAxisAngle(new Vector3(tempInfo.Qua[0], tempInfo.Qua[1], tempInfo.Qua[2]), tempInfo.Qua[3]);
mtx.makeRotationFromQuaternion(quaternion);
}
if (tempInfo.Pos)
{
mtx.setPosition(...tempInfo.Pos);
}
}
const size = new Vector3().fromArray(tempInfo.BoxSize ? tempInfo.BoxSize : [tempInfo.Lenght, tempInfo.Width, tempInfo.Height]);
newTemp.SetParamExpr("L", size.x);
newTemp.SetParamExpr("W", size.y);
newTemp.SetParamExpr("H", size.z);
if (tempInfo.ParamMap)
{
for (const mk of tempInfo.ParamMap)
{
const param = newTemp.GetParam(mk.name);
if (param && param.type === TemplateParamType.Float)
{
param.expr = mk.value;
}
}
}
await newTemp.UpdateTemplateTree();
let ens = newTemp.AllEntitys as Entity[];
for (const en of ens)
{
if (en instanceof Board)
{
en.BoardProcessOption[EBoardKeyList.RoomName] = tempInfo.RoomName;
en.BoardProcessOption[EBoardKeyList.CabinetName] = tempInfo.CabinetName;
}
else if (en instanceof HardwareCompositeEntity)
{
en.HardwareOption[EBoardKeyList.RoomName] = tempInfo.RoomName;
en.HardwareOption[EBoardKeyList.CabinetName] = tempInfo.CabinetName;
}
en.ApplyMatrix(new Matrix4().premultiply(mtx));
}
}
return newTemp;
}
export async function ParseHardwareInfo(newTemp: TemplateRecord, el: CFHardware, cuDb: Database)
{
const ParseHardwareParam = (en: HardwareCompositeEntity, el: CFHardware) =>
{
const option = en.HardwareOption;
option.name = el.Name ?? "";
option.unit = el.Unit ?? "个";
option.actualExpr = el.ActualExpr ?? "";
option.model = el.Model ?? "";
option.factory = el.Factory ?? "";
option.brand = el.Brand ?? "";
option.spec = el.Spec ?? "";
option.comments = el.Comments ?? "";
option.isHole = el.IsHole ?? false;
option.material = el.Material ?? "";
option.color = el.Color ?? "";
};
if (newTemp)
{
let ens = newTemp.AllEntitys as Entity[];
for (const en of ens)
{
if (en instanceof Board)
{
en.BoardProcessOption[EBoardKeyList.RoomName] = el.RoomName;
en.BoardProcessOption[EBoardKeyList.CabinetName] = el.CabinetName;
}
else if (en instanceof HardwareCompositeEntity)
{
en.HardwareOption[EBoardKeyList.RoomName] = el.RoomName;
en.HardwareOption[EBoardKeyList.CabinetName] = el.CabinetName;
ParseHardwareParam(en, el);
}
}
return newTemp;
}
let hw = new HardwareCompositeEntity();
let en = new Board();
const boxSize = new Vector3().fromArray(el.BoxSize ? el.BoxSize : [el.Lenght, el.Width, el.Height]);
[en.Width, en.Height, en.Thickness] = [boxSize.x, boxSize.y, boxSize.z];
hw.Entitys.push(en);
hw.HardwareOption[EBoardKeyList.RoomName] = el.RoomName;
hw.HardwareOption[EBoardKeyList.CabinetName] = el.CabinetName;
ParseHardwareParam(hw, el);
cuDb.ModelSpace.Append(hw);
return hw;
}
export async function ParseToplineInfo(contour: Polyline, el: CFTopline, cuDb: Database)
{
const ParseHardwareParam = (en: HardwareTopline | HardwareCompositeEntity, el: CFTopline) =>
{
const option = en.HardwareOption;
option.name = el.Name ?? "";
option.unit = el.Unit ?? "毫米";
option.actualExpr = el.ActualExpr ?? "";
option.model = el.Model ?? "";
option.factory = el.Factory ?? "";
option.brand = el.Brand ?? "";
option.spec = el.Spec ?? "";
option.comments = el.Comments ?? "";
};
const parseCurve = new ParseCurve();
if (!contour && el.Contour)
{
contour = parseCurve.ParsePolyline(el.Contour);
}
let pathCurve: Curve;
if (el.PathCurve)
{
if ((el.PathCurve as CircleContour).Center !== undefined)
{
const { Center, Radius } = el.PathCurve as CircleContour;
pathCurve = parseCurve.ParseCircle(Radius, Center);
}
else
pathCurve = parseCurve.ParsePolyline(el.PathCurve, true);
}
const topline = new HardwareTopline(contour, pathCurve);
topline.HardwareOption[EBoardKeyList.RoomName] = el.RoomName;
topline.HardwareOption[EBoardKeyList.CabinetName] = el.CabinetName;
ParseHardwareParam(topline, el);
cuDb.ModelSpace.Append(topline);
return topline;
}

@ -0,0 +1,414 @@
晨丰导入
//通用类型定义
type CurverType = "Curve" | "Polyline" | "Rect" | "Line" | "Arc" | "Circle";
type EntityType = "Entity" | "ExtrudeSolid" | "Board" | "Template" | "EntityTree" | "Hardware" | "Topline";
// ContourCurve 定义轮廓曲线,每个点的坐标和弯曲度,
// pt为点坐标,bul为弯曲度(区间-1~1),俗称弓弦比
// bul为0时为直线,bul为0.5时为半圆,正负为上下弯曲的方向
// bul值为(弧线两点直线的中点到弧线中点的距离)除以(弧线两点直线的中点到弧线起点的距离)
type PolylineContour = { pt: [number, number], bul: 0; }[]; //多段线轮廓
type CircleContour = { Radius: number, Center: [number, number, number]; }; //圆形轮廓
type ExtrudeContour = PolylineContour | CircleContour;
图纸结构
1.模型空间 ModelSpace 结构
定义模型空间,包含所有实体类
ModelSpace [
Board, //板类
Temple, //模板类
Entity, //其他实体类
EntityTree, //实体模板树类
]
模型中所有实体遵循自身坐标系定位
2.实体基类 CFEntity 结构
定义实体类,包含所有实体通用属性
export interface CFEntity
{
Type: EntityType | CurverType; //实体类型
Id?: number; //自定义id加工组使用
ColorIndex?: number; //颜色索引 值区间0-255
// 定位方式选择 OCS 或 pos(位置) + rot(旋转) 或 pos(位置) + Qua(四元数)
OCS?: number[]; //OCS矩阵 长度16的数组
//定位方式 pos(位置) rot(旋转)
Pos?: [number, number, number]; //位置
Rot?: [number, number, number]; //欧拉旋转角
// Or
Qua?: [number, number, number, number]; //四元数旋转角
}
实体类型判断 Type 字段(必填)
Type: "Curve" | "Line" | "Point" | "Circle" | "Entity" | "ExtrudeSolid" | "Board" | "Template" | "EntityTree"
定位方式选择 OCS 或 pos(位置) + rot(旋转) 或 pos(位置) + Qua(四元数)
例:
{
Type:"Entity", //类型实体
colorIndex:0, //颜色索引(选填),默认值7白色
OCS: [1,0,0,0,0,0,1,0,0,-1,0,0,0,0,100,1], //x轴旋转90度,z轴向上平移100
pos: [0, 0, 100],
rot: [90, 0, 0],
pos: [0, 0, 100],
Qua: [0.7071, 0, 0, 0.7071, 0, 0, 0]
}
3.拉伸实体类 继承 CFEntity
定义拉伸实体类通用属性
export interface CFExtrudeSolid extends CFEntity
{
// Type: "ExtrudeSolid" //类型拉伸实体(必填)
Width?: number; //宽
Height?: number; //高
// Or
ContourCurve?: ExtrudeContour; //轮廓曲线
Thickness?: number; //厚度
GroovesAddLength?: number; //槽加长
GroovesAddWidth?: number; //槽加宽
GroovesAddDepth?: number; //槽加深
KnifeRadius?: number; //刀半径
//孔洞本质上也是拉伸实体,一般孔洞只需要提供位置,轮廓曲线和厚度即可
Holes?: CFExtrudeSolid[]; //孔洞
}
例:
{
Type:"ExtrudeSolid",
...实体类属性
Width:100,
Height:200,
//或
ContourCurve:[{pt: [0,0], bul: 0;},{pt: [100,0], bul: 0;},{pt: [100,200], bul: 0;},{pt: [0,200], bul: 0;},{pt: [0,0], bul: 0;}]
thickness:18,
GroovesAddLength:0,
GroovesAddWidth:0,
GroovesAddDepth:0,
KnifeRadius:3,
Holes:[]
}
Holes 孔洞本质上也是拉伸实体,一般孔洞只需要提供位置,轮廓曲线和厚度即可
例:
{
Type:"ExtrudeSolid",
...拉伸实体类属性
Width:100,
Height:200,
//或
ContourCurve:[{pt: [0,0], bul: 0;},{pt: [10,0], bul: 0;},{pt: [10,20], bul: 0;},{pt: [0,20], bul: 0;}]
thickness:10,
}
4.画板类 CFBoard 继承 CFExtrudeSolid
定义板类通用属性
export interface CFBoard extends CFExtrudeSolid
{
// Type: "Board"; //类型板(必填)
Name?: string; //板名称
BrType?: number; //板类型(选填) 0:层板,1:立板,2:背板
//定位类型0-3
PositionType?: number; //定位类型(选填) 0:晨丰基点(默认),1:基于板盒子最小点,2:基于板盒子中心点
OpenDir?: number; //打开方向(选填) 0:非门板(默认),1:左开门板,2:右开门板,3:上开门板,4:下开门板,
//纹路0-2
Lines?: number; //纹路(选填) 0:正纹(默认),1:反,2:可翻转
BigHole?: number; //大孔面(选填) 0:正(默认),1:反
ComposingFace?: number; //排版面(选填) 0:正面,1:背面,2:随意面(默认)
RoomName?: string; //房名
CabinetName?: string; //柜名
BrMatName?: string; //板材名
Matrial?: string; //材料
Color?: string; //颜色
//板材信息可以自定义写入,也可以通过材质编码ID获取对应的值
BoardMaterialId?: string; //板材信息Id
UpSealed?: string; //封边上下左右
DownSealed?: string;
LeftSealed?: string;
RightSealed?: string;
// 封边信息
// 普通板时使用 UpSealed,DownSealed,LeftSealed,RightSealed 表示上下左右封边的值
// 异形板时使用 EachSealeds 数组表示每个边的封边数据,size表示封边的厚度
EachSealeds?: { size: number; }[]; //每个边的封边数据
EachEdgeDrills?: string[]; //每个边的排钻数据
FrontDrill?: boolean; //正排孔面
BackDrill?: boolean; //反排孔面
Remarks?: [string, string][]; //备注
}
例:
{
Type: "Board",
...拉伸实体类属性
ContourCurve: [{ pt: [0, 0], bul: 0 },{ pt: [0, 200], bul: 0 },{ pt: [100, 200], bul: 0 },{ pt: [100, 0], bul: 0 }],
Thickness: 18,
ColorIndex: 2,
Rot: [90, 0, 0],
Pos: [-200, 0, 0],
Name: "层板",
RoomName:"房名",
CabinetName:"柜名",
BrType: 0,
PositionType: 0,
OpenDir: 0,
Lines:0,
BigHole:0,
ComposingFace:2,
BrMatName: "默认板材5厘",
Matrial:"生态板",
Color:"经典檀木",
//或
BoardMaterialId:"SP202104121",
UpSealed: "1",
DownSealed: "1",
LeftSealed: "1",
RightSealed: "1",
//或
EachSealeds: [{ size: 1 }, { size: ,1 }, { size: 1 }, { size: 1 }, { size: 1 }],
EachEdgeDrills: ["不排", "不排", "不排", "不排"],
FrontDrill:true,
BackDrill:true,
Remarks: [["备注", "层板"],["备注2", "层板2"]],
}
板材信息可以自定义写入,也可以通过材质编码ID获取对应的值
封边信息
普通板时使用 UpSealed,DownSealed,LeftSealed,RightSealed 表示上下左右封边的值
异形板时使用 EachSealeds 数组表示每个边的封边数据,size表示封边的厚度
5.模板类 CFTemplate 继承 CFEntity
export interface CFTemplate extends CFEntity
{
// Type: "Template"; //类型模板(必填)
TempalteId?: string; //模板ID
Name?: string; //模板名称
//模块参数
Lenght?: number; //长度
Width?: number; //宽度
Height?: number; //高度
// Or
BoxSize?: [number, number, number]; //盒子尺寸
ParamMap?: { name: string, value: string; }[]; //模块参数
RoomName?: string; //房名
CabinetName?: string; //柜名
}
例:
{
Type: "Template",
TempalteId: "1923",
Name: "模板1",
Lenght: 100,
Width: 100,
Height: 100,
//Or
BoxSize: [100, 100, 100],
RoomName: "模板主卧",
CabinetName: "模板标准柜",
Rot: [90, 0, 0],
Pos: [400, 0, 0],
ParamMap:
[
{
name: "CZ",
value: "1137"
},
{
name: "QT",
value: "123"
}
]
}
6.实体树类 CFEntityTree 结构 继承 CFEntity
定义实体树类
export interface CFEntityTree extends CFEntity
{
// Type: "EntityTree"; //类型实体树(必填)
Name?: string; //模板空间名称
Entitys?: CFEntity[]; //实体数组
Childen?: CFEntityTree[]; //子模板数组
}
例:
{
Type:"EntityTree",
Name:"模板1",
Children:[
{
Type:"EntityTree",
Name:"模板2",
Entitys:[
{
Type:"Entity",
Name:"实体1",
},
{
Type:"Entity",
Name:"实体2",
}
]
}
]
}
实体树中的实体位置由实体自身的位置决定
7.五金实体类 CFHardware 继承 CFTemplate
定义五金实体类
export interface CFHardware extends CFTemplate
{
// Type: "Hardware"; //类型五金(必填)
Name?: string; //五金名称
HardwarerId?: string; //五金模板ID
Unit?: string; //单位
ActualExpr?: string; //价格表达式
Model?: string; //型号
Factory?: string; //厂家
Brand?: string; //品牌
Spec?: string; //规格
Comments?: string; //备注
IsHole?: boolean; //是否挖孔
Material?: string; //材质
Color?: string; //颜色
}
例:
{
Type: "Hardware",
...模板属性
HardwarerId: "44444444",
Name: "五金",
Unit: "个",
ActualExpr: "L*W*H",
Model: "X-1",
Factory: "厂家晨丰",
Brand: "品牌晨丰",
Spec: "{L*2}",
Comments: "五金备注",
IsHole: true,
Material: "五金材质",
Color: "五金颜色",
}
当提供HardwareId时,五金实体会根据ID获取返回一个五金模板,
没有提供HardwareId时,返回一个虚拟五金实体
8.顶线实体类 CFTopLine 继承 CFTemplate
定义顶线实体类
export interface CFTopline extends CFTemplate
{
// Type: "Topline"; //类型顶线(必填)
Name?: string; //顶线名称
ToplineId?: string; //顶线横截面轮廓模板ID
Unit?: string; //单位
ActualExpr?: string; //价格表达式
Model?: string; //型号
Factory?: string; //厂家
Brand?: string; //品牌
Spec?: string; //规格
Comments?: string; //备注
Contour?: { pt: [number, number], bul: 0; }[]; //横截面轮廓曲线
PathCurve?: ExtrudeContour; //绘制路径曲线
}
例1:
{
Type: "Topline",
...模板属性
ToplineId: "55555555",
Name: "顶线",
Unit: "个",
ActualExpr: "L*W*H",
Model: "X-1",
Factory: "厂家晨丰",
Brand: "品牌晨丰",
Spec: "{L*2}",
Comments: "顶线备注",
PathCurve: [
{ pt: [0, 0], bul: 0 },
{ pt: [100, 0], bul: 0 },
{ pt: [100, 200], bul: 0 },
{ pt: [0, 200], bul: 0 },
{ pt: [0, 0], bul: 0 }
],
}
例2
{
Type: "Topline",
...模板属性
Name: "顶线",
Unit: "个",
ActualExpr: "L*W*H",
Model: "X-1",
Factory: "厂家晨丰",
Brand: "品牌晨丰",
Spec: "{L*2}",
Comments: "顶线备注",
Contour: [
{ pt: [0, 0], bul: 0 },
{ pt: [0, 10], bul: 0 },
{ pt: [10, 10], bul: 0 },
{ pt: [10, 0], bul: 0 }
{ pt: [0, 0], bul: 0 },
],
PathCurve: [
{ pt: [0, 0], bul: 0 },
{ pt: [100, 0], bul: 0 },
{ pt: [100, 200], bul: 0 },
{ pt: [0, 200], bul: 0 },
{ pt: [0, 0], bul: 0 }
],
}
当提供ToplineId时,顶线实体会根据ID获取顶线模板的横截面轮廓,通过绘制路径轮廓进行绘制顶线
没有提供ToplineId时,顶线会根据提供的横截面轮廓,通过绘制路径轮廓进行绘制顶线

@ -34,9 +34,9 @@ import { XAxis, YAxis, ZAxis, ZeroVec, equaln } from "../../../Geometry/GeUtils"
import { GetSealedBoardContour } from "../../../GraphicsSystem/CalcEdgeSealing";
import { AppToaster } from "../../../UI/Components/Toaster";
import { CuttingBoardByBoard } from "../../BoardCutting/CuttingUtils2";
import { BoardMaterialLoader, MaterialInfo } from "../../CF/Import/BoardMaterialLoader";
import { FaceDirection } from "../../DrawDrilling/DrillType";
import { IBoardRectHoleType, SetBrHighHoleTypeFromRectHoleType } from "../../DrawDrilling/HoleUtils";
import { JiaJuLoader, MaterialInfo } from "./JiaJuLoader";
let _xmlParse: DOMParser;
@ -171,7 +171,7 @@ class JiaJuParse
async Do()
{
this.ParseRoomNameMap();
const jiaJuLoader = new JiaJuLoader();
const jiaJuLoader = new BoardMaterialLoader();
await jiaJuLoader.LoaderMaterialInfo();
this.Code_MaterialInfo = jiaJuLoader.Code_MaterialInfo;
for (let ps of this.bom.Products[0].Product)

@ -7,6 +7,7 @@ export enum CommandNames
KJLMaterialMap = "KJLMATERIALMAP",
Clearkjltoken = "CLEARKJLTOKEN",
JiaJuImport = "JIAJUIMPORT",
CFImport = "CFIMPORT",
Group = "GROUP",
DXFImport = "DXF",
DWGImport = "DWG",

@ -211,6 +211,7 @@ import { Command_GroovesModify } from "../Add-on/showModal/GroovesModify";
import { ShowEditorBBS } from "../Add-on/showModal/ShowModal";
// import { DrawFloor } from '../Add-on/DrawFloor';
// import { RevTarget, SaveTarget } from '../Add-on/RenderTarget';
import { ImportCFData } from "../Add-on/CF/Import/CFImport";
import { ChangeColorByRoomCabinet } from "../Add-on/ChangeColorByRoomOrCabinet/ChangeColorByRoomOrCabinet";
import { Command_RemovePolylineRepeatPos } from "../Add-on/Cmd_RemovePolylineRepeatPos";
import { Command_Modeling } from "../Add-on/Command_Modeling";
@ -317,6 +318,9 @@ export function registerCommand()
//嘉居
commandMachine.RegisterCommand(CommandNames.JiaJuImport, new Command_JiaJuImport());
//晨丰导入
commandMachine.RegisterCommand(CommandNames.CFImport, new ImportCFData());
//编组
commandMachine.RegisterCommand(CommandNames.Group, new Command_Group());
commandMachine.RegisterCommand(CommandNames.UnGroup, new Command_UnGroup());

@ -2246,6 +2246,15 @@ export const CommandList: ICommand[] = [
chName: "嘉居导入",
chDes: "从嘉居导入数据",
},
{
typeId: "util",
link: `#`,
defaultCustom: "CF",
command: CommandNames.CFImport,
type: "工具",
chName: "晨丰导入",
chDes: "晨丰文档导入数据",
},
{
typeId: "util",
link: `#`,

@ -4,9 +4,10 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { app } from '../../../ApplicationServices/Application';
import { ToplineUrls } from '../../../Common/HostUrl';
import { inflateBase64 } from "../../../Common/inflate";
import { PostJson, RequestStatus } from '../../../Common/Request';
import { deflate, getPolylineSVG, toplineFileIn } from '../../../Common/SerializeMaterial';
import { copyTextToClipboard } from '../../../Common/Utils';
import { inflateBase64 } from "../../../Common/inflate";
import { CADFiler } from '../../../DatabaseServices/CADFiler';
import { Polyline } from '../../../DatabaseServices/Entity/Polyline';
import { CommandWrap } from '../../../Editor/CommandMachine';
@ -174,6 +175,11 @@ export class ToplineList extends React.Component<IToplineListProps, { isContextM
text="重选轮廓"
onClick={() => this.props.updata("", null, this.props.getData)}
/>
<MenuItem
icon="duplicate"
text="复制ID"
onClick={() => this.copyId(tpline.topline_id)}
/>
<MenuItem
icon="trash"
text="删除"
@ -192,6 +198,16 @@ export class ToplineList extends React.Component<IToplineListProps, { isContextM
e.stopPropagation();
e.preventDefault();
};
//复制ID
private copyId = (toplineId: string) =>
{
copyTextToClipboard(toplineId);
AppToaster.show({
message: "ID复制成功",
intent: Intent.SUCCESS
});
};
public render()
{
return (

Loading…
Cancel
Save