mirror of https://gitee.com/cf-fz/WebCAD.git
parent
8cf6f2fb23
commit
521b17a7ac
@ -0,0 +1,51 @@
|
||||
import { Board } from "../../DatabaseServices/Entity/Board";
|
||||
import { Curve } from "../../DatabaseServices/Entity/Curve";
|
||||
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
|
||||
import { Vector3 } from "three";
|
||||
|
||||
export function GetHoleCurves(br: Board)
|
||||
{
|
||||
let con = br.ContourCurve.Clone() as Polyline;
|
||||
|
||||
let cus: Curve[] = [];
|
||||
|
||||
if (br.IsSpecialShape)
|
||||
{
|
||||
//板构建曲线方向
|
||||
let dir = Math.sign(br.ContourCurve.Area2);
|
||||
//让板件轮廓统一逆时针
|
||||
if (dir < 0)
|
||||
con.Reverse();
|
||||
|
||||
let cs = con.Explode();
|
||||
while (cs.length > 0)
|
||||
{
|
||||
let c = cs.shift();//取第一个
|
||||
|
||||
while (true)
|
||||
{
|
||||
let deleteCount = 0;
|
||||
for (let i = 0; i < cs.length; i++)
|
||||
{
|
||||
if (!c.Join(cs[i]))
|
||||
{
|
||||
deleteCount = cs.splice(0, i).length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//如果c和剩余的轮廓都不相交,那么退出
|
||||
if (deleteCount === 0)
|
||||
{
|
||||
cus.push(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cus = new Polyline().RectangleFrom2Pt(new Vector3(), new Vector3(br.Width, br.Height)).Explode();
|
||||
}
|
||||
return cus;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import { Command } from "../../Editor/CommandMachine";
|
||||
import { app } from "../../ApplicationServices/Application";
|
||||
import { ModalPosition } from "../../UI/Components/Modal/ModalsManage";
|
||||
import { DrillingTemplateManage } from "../../UI/Components/Modal/DrillingTemplateManage";
|
||||
|
||||
export class ShowDrillingTemplate implements Command
|
||||
{
|
||||
async exec()
|
||||
{
|
||||
app.Editor.ModalManage.RenderModal(DrillingTemplateManage, ModalPosition.Center, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
import { Matrix4, Vector3 } from "three";
|
||||
import { app } from "../ApplicationServices/Application";
|
||||
import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
|
||||
import { Circle } from "../DatabaseServices/Entity/Circle";
|
||||
import { ExtureContourCurve } from "../DatabaseServices/Entity/Extrude";
|
||||
import { Polyline } from "../DatabaseServices/Entity/Polyline";
|
||||
import { Command } from "../Editor/CommandMachine";
|
||||
import { JigUtils } from "../Editor/JigUtils";
|
||||
import { PromptEntityResult, PromptStatus } from "../Editor/PromptResult";
|
||||
import { isParallelTo, equalv3 } from "../Geometry/GeUtils";
|
||||
|
||||
export class DrawExtrude implements Command
|
||||
{
|
||||
async exec()
|
||||
{
|
||||
let contour: ExtureContourCurve;
|
||||
let contourRes: PromptEntityResult;
|
||||
while (true)
|
||||
{
|
||||
contourRes = await app.Editor.GetEntity({
|
||||
Msg: "选择封闭的轮廓",
|
||||
Filter: {
|
||||
filterTypes: [Polyline, Circle],
|
||||
filterFunction: (obj, en: ExtureContourCurve) => en.IsClose
|
||||
}
|
||||
});
|
||||
|
||||
if (contourRes.Status === PromptStatus.OK && contourRes.Entity)
|
||||
{
|
||||
contour = contourRes.Entity.Clone() as ExtureContourCurve;
|
||||
break;
|
||||
}
|
||||
else if (contourRes.Status === PromptStatus.Cancel)
|
||||
break;
|
||||
}
|
||||
if (!contour) return;
|
||||
|
||||
let oldUcs = app.Editor.UCSMatrix;
|
||||
let en = JigUtils.Draw(new ExtrudeHole());
|
||||
let appleMat = ExtrudeApplyContour(en, contour);
|
||||
en.ApplyMatrix(new Matrix4().getInverse(appleMat));
|
||||
app.Editor.UCSMatrix = contour.OCS.setPosition(new Vector3);
|
||||
let oldPosition = en.Position;
|
||||
|
||||
let basePt: Vector3;
|
||||
if (contourRes.Entity instanceof Circle)
|
||||
basePt = contourRes.Entity.Center;
|
||||
else
|
||||
basePt = contourRes.Entity.BoundingBox.getCenter(new Vector3);
|
||||
|
||||
let distRes = await app.Editor.GetDistance({
|
||||
Msg: "请输入厚度,或者点取距离",
|
||||
Default: 1,
|
||||
BasePoint: basePt,
|
||||
Callback: (d) =>
|
||||
{
|
||||
this.SetHeight(en, d, basePt, oldPosition);
|
||||
}
|
||||
});
|
||||
if (distRes.Status !== PromptStatus.OK)
|
||||
{
|
||||
app.Editor.UCSMatrix = oldUcs;
|
||||
return;
|
||||
}
|
||||
this.SetHeight(en, distRes.Distance, basePt, oldPosition);
|
||||
app.Editor.UCSMatrix = oldUcs;
|
||||
|
||||
let radRes = await app.Editor.GetDistance({
|
||||
Msg: "请输入走刀半径",
|
||||
Default: 3,
|
||||
})
|
||||
|
||||
if (radRes.Status !== PromptStatus.OK) return;
|
||||
en.KnifeRadius = radRes.Distance;
|
||||
app.Database.ModelSpace.Append(en);
|
||||
contourRes.Entity.Erase();
|
||||
}
|
||||
private SetHeight(en: ExtrudeHole, dist: number, basePt: Vector3, oldPosition: Vector3)
|
||||
{
|
||||
en.Height = dist;
|
||||
let nor = en.Normal;
|
||||
let vNor = app.Viewer.WorldToScreen(nor.clone()).setZ(0);
|
||||
vNor = vNor.setY(app.Viewer.Height - vNor.y);
|
||||
|
||||
let vZero = app.Viewer.WorldToScreen(new Vector3);
|
||||
vZero = vZero.setY(app.Viewer.Height - vZero.y);
|
||||
vNor.sub(vZero);
|
||||
|
||||
let curPt = app.Editor.MouseCtrl.m_CurMousePointVCS.clone();
|
||||
curPt = curPt.setY(app.Viewer.Height - curPt.y);
|
||||
|
||||
let vBasePt = app.Viewer.WorldToScreen(basePt.clone()).setZ(0);
|
||||
vBasePt = vBasePt.setY(app.Viewer.Height - vBasePt.y);
|
||||
|
||||
let dir = curPt.sub(vBasePt);
|
||||
|
||||
if (vNor.angleTo(dir) <= Math.PI / 2)
|
||||
en.Position = oldPosition;
|
||||
else
|
||||
en.Position = oldPosition.clone().add(nor.multiplyScalar(-dist));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function ExtrudeApplyContour(ext: ExtrudeHole, contour: ExtureContourCurve): Matrix4 | undefined
|
||||
{
|
||||
let applyMatrix: Matrix4;
|
||||
|
||||
contour = contour.Clone();
|
||||
if (equalv3(ext.Normal, contour.Normal))
|
||||
applyMatrix = ext.OCSInv;
|
||||
else if (equalv3(
|
||||
contour.Normal,
|
||||
new Vector3().setFromMatrixColumn(app.Editor.UCSMatrix, 2)
|
||||
))
|
||||
applyMatrix = app.Editor.UCSMatrixInv;
|
||||
else
|
||||
applyMatrix = contour.OCSInv;
|
||||
|
||||
contour.ApplyMatrix(applyMatrix);
|
||||
|
||||
let box = contour.BoundingBox;
|
||||
contour.Position = contour.Position.sub(box.min);
|
||||
ext.ContourCurve = contour;
|
||||
|
||||
//修正矩阵的基点
|
||||
applyMatrix.elements[12] -= box.min.x;
|
||||
applyMatrix.elements[13] -= box.min.y;
|
||||
applyMatrix.elements[14] -= box.min.z;
|
||||
return applyMatrix;
|
||||
}
|
@ -0,0 +1,354 @@
|
||||
import { BufferGeometry, ExtrudeGeometry, ExtrudeGeometryOptions, Geometry, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Vector3 } from "three";
|
||||
import { arrayClone, arrayLast, arraySortByNumber } from "../../Common/ArrayExt";
|
||||
import { ColorMaterial } from "../../Common/ColorPalette";
|
||||
import { DisposeThreeObj } from "../../Common/Dispose";
|
||||
import { Vector2ApplyMatrix4 } from "../../Common/Matrix4Utils";
|
||||
import { ObjectSnapMode } from "../../Editor/ObjectSnapMode";
|
||||
import { FastWireframe2 } from "../../Geometry/CreateWireframe";
|
||||
import { EdgesGeometry } from "../../Geometry/EdgeGeometry";
|
||||
import { equaln, equalv2, equalv3, ZeroVec } from "../../Geometry/GeUtils";
|
||||
import { RenderType } from "../../GraphicsSystem/RenderType";
|
||||
import { Factory } from "../CADFactory";
|
||||
import { CADFiler } from "../CADFiler";
|
||||
import { Contour } from "../Contour";
|
||||
import { DragPointType } from "../Entity/DragPointType";
|
||||
import { ExtureContourCurve } from "../Entity/Extrude";
|
||||
import { Polyline } from "../Entity/Polyline";
|
||||
import { Shape } from "../Shape";
|
||||
import { Hole } from "./Hole";
|
||||
|
||||
@Factory
|
||||
export class ExtrudeHole extends Hole
|
||||
{
|
||||
private _contourCurve: ExtureContourCurve = new Polyline();
|
||||
private _EdgeGeometry: EdgesGeometry;
|
||||
protected _knifeRadius: number = 3;
|
||||
get KnifeRadius()
|
||||
{
|
||||
return this._knifeRadius;
|
||||
}
|
||||
set KnifeRadius(v: number)
|
||||
{
|
||||
if (!equaln(v, this._knifeRadius))
|
||||
{
|
||||
this.WriteAllObjectRecord();
|
||||
this._knifeRadius = v;
|
||||
}
|
||||
}
|
||||
get ContourCurve()
|
||||
{
|
||||
return this._contourCurve;
|
||||
}
|
||||
|
||||
set ContourCurve(curve: ExtureContourCurve)
|
||||
{
|
||||
if (!curve.IsClose) return;
|
||||
|
||||
if (curve instanceof Polyline)
|
||||
{
|
||||
curve.CloseMark = true;
|
||||
let pts = curve.LineData;
|
||||
if (equalv2(pts[0].pt, arrayLast(pts).pt))
|
||||
pts.pop();
|
||||
|
||||
//如果曲线被旋转了,那么修正它的旋转矩阵,避免纹路错误
|
||||
let ocs = curve.OCS;
|
||||
if (!equaln(ocs.elements[0], 1))// || ocs.elements[9] || ocs.elements[10]
|
||||
{
|
||||
for (let p of pts)
|
||||
Vector2ApplyMatrix4(ocs, p.pt);
|
||||
curve.OCS = new Matrix4();
|
||||
}
|
||||
curve.ClearDraw();
|
||||
}
|
||||
|
||||
this.WriteAllObjectRecord();
|
||||
this._contourCurve = curve;
|
||||
this.CheckContourCurve();
|
||||
this.Update();
|
||||
}
|
||||
CheckContourCurve()
|
||||
{
|
||||
let box = this._contourCurve.BoundingBox;
|
||||
|
||||
//修正轮廓基点
|
||||
if (!equalv3(box.min, ZeroVec))
|
||||
{
|
||||
this._contourCurve.Position =
|
||||
this._contourCurve.Position.sub(box.min);
|
||||
|
||||
let v = box.min.applyMatrix4(this.OCS.setPosition(ZeroVec));
|
||||
this._Matrix.setPosition(this.Position.add(v));
|
||||
}
|
||||
}
|
||||
GetObjectSnapPoints(
|
||||
snapMode: ObjectSnapMode,
|
||||
pickPoint: Vector3,
|
||||
lastPoint: Vector3,
|
||||
viewXform?: Matrix3
|
||||
): Vector3[]
|
||||
{
|
||||
switch (snapMode)
|
||||
{
|
||||
case ObjectSnapMode.End:
|
||||
return this.GetStretchPoints();
|
||||
case ObjectSnapMode.Mid:
|
||||
case ObjectSnapMode.Cen:
|
||||
case ObjectSnapMode.Nea:
|
||||
case ObjectSnapMode.Ext:
|
||||
case ObjectSnapMode.Per:
|
||||
case ObjectSnapMode.Tan:
|
||||
{
|
||||
let contour = this.ContourCurve.Clone();
|
||||
contour.ApplyMatrix(this.OCS);
|
||||
let pts = contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform);
|
||||
|
||||
contour.Position = contour.Position.add(this.Normal.multiplyScalar(this.Height));
|
||||
pts.push(
|
||||
...contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform)
|
||||
);
|
||||
return pts;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
get Shape()
|
||||
{
|
||||
let contour = Contour.CreateContour(this.ContourCurve.Clone(), false);
|
||||
|
||||
return new Shape(contour);
|
||||
}
|
||||
get BoundingBoxInOCS()
|
||||
{
|
||||
let box = this.ContourCurve.BoundingBox;
|
||||
box.max.add(new Vector3(0, 0, this.Height));
|
||||
return box;
|
||||
}
|
||||
get BoundingBox()
|
||||
{
|
||||
let box = this.ContourCurve.BoundingBox;
|
||||
box.max.add(new Vector3(0, 0, this.Height));
|
||||
box.applyMatrix4(this.OCS);
|
||||
return box;
|
||||
}
|
||||
private get EdgeGeometry()
|
||||
{
|
||||
if (this._EdgeGeometry)
|
||||
return this._EdgeGeometry;
|
||||
|
||||
this._EdgeGeometry = new EdgesGeometry().FromGeometry(this.MeshGeometry);
|
||||
return this._EdgeGeometry;
|
||||
}
|
||||
private _MeshGeometry: BufferGeometry | Geometry;
|
||||
private get MeshGeometry()
|
||||
{
|
||||
if (this._MeshGeometry)
|
||||
return this._MeshGeometry;
|
||||
|
||||
this._MeshGeometry = this.GeneralMeshGeometry();
|
||||
return this._MeshGeometry;
|
||||
}
|
||||
private GeneralMeshGeometry()
|
||||
{
|
||||
let extrudeSettings: ExtrudeGeometryOptions = {
|
||||
steps: 1,
|
||||
bevelEnabled: false,
|
||||
depth: this.Height,
|
||||
};
|
||||
let geo = new ExtrudeGeometry(this.ContourCurve.Shape, extrudeSettings);
|
||||
geo.applyMatrix(this._contourCurve.OCS);
|
||||
return geo;
|
||||
}
|
||||
GetGripOrStretchPoints(dragType: DragPointType)
|
||||
{
|
||||
let isGrip = dragType === DragPointType.Grip;
|
||||
|
||||
let pts = isGrip ? this.ContourCurve.GetGripPoints() : this.ContourCurve.GetStretchPoints();
|
||||
let v = new Vector3(0, 0, this.Height);
|
||||
pts.push(...pts.map(p => p.clone().add(v)));
|
||||
pts.forEach(p => { p.applyMatrix4(this.OCS) });
|
||||
|
||||
return pts;
|
||||
}
|
||||
private GetStrectchPointCountList(dragType: DragPointType): number
|
||||
{
|
||||
return this.ContourCurve.GetDragPointCount(dragType) * 2;
|
||||
}
|
||||
MoveGripOrStretchPoints(indexList: number[], vec: Vector3, dragType: DragPointType)
|
||||
{
|
||||
this.WriteAllObjectRecord();
|
||||
if (dragType === DragPointType.Stretch && indexList.length === this.GetStrectchPointCountList(dragType))
|
||||
{
|
||||
this.Position = this.Position.add(vec);
|
||||
return;
|
||||
}
|
||||
arraySortByNumber(indexList);
|
||||
this.MoveGripOrStretchPointsOnly(indexList, vec, dragType);
|
||||
this.CheckContourCurve();
|
||||
this.Update();
|
||||
}
|
||||
IsStretchHeight(indexs: number[])
|
||||
{
|
||||
let count = this.ContourCurve.GetStretchPoints().length;
|
||||
if (indexs.length === count)
|
||||
{
|
||||
let isF = indexs[0] < count;
|
||||
return indexs.every(i => isF === (i < count));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
MoveGripOrStretchPointsOnly(indexList: Array<number>, vec: Vector3, dragType: DragPointType)
|
||||
{
|
||||
let stretchCount = this.ContourCurve.GetDragPointCount(dragType);
|
||||
|
||||
if (dragType === DragPointType.Stretch)
|
||||
{
|
||||
//Move
|
||||
if (indexList.length === stretchCount * 2)
|
||||
{
|
||||
this.Position = this.Position.add(vec);
|
||||
return;
|
||||
}
|
||||
|
||||
//判断是否拉伸厚度
|
||||
if (this.IsStretchHeight(indexList))
|
||||
{
|
||||
let isFront = indexList[0] < stretchCount;
|
||||
|
||||
if (indexList.every(v => v < stretchCount === isFront))
|
||||
{
|
||||
//Change thickness
|
||||
let lvec = vec.clone().applyMatrix4(this.OCSInv.setPosition(ZeroVec));
|
||||
if (isFront)
|
||||
{
|
||||
this.Height -= lvec.z;
|
||||
//移动位置而不改变内部拉槽
|
||||
let v = this.Normal.multiplyScalar(lvec.z);
|
||||
this._Matrix.elements[12] += v.x;
|
||||
this._Matrix.elements[13] += v.y;
|
||||
this._Matrix.elements[14] += v.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Height += lvec.z;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
indexList = arrayClone(indexList);
|
||||
}
|
||||
|
||||
//修正点的索引
|
||||
for (let i = 0; i < indexList.length; i++)
|
||||
{
|
||||
let index = indexList[i];
|
||||
if (index >= stretchCount)
|
||||
{
|
||||
index -= stretchCount;
|
||||
indexList[i] = index;
|
||||
}
|
||||
}
|
||||
|
||||
indexList = [...new Set(indexList)];
|
||||
|
||||
let localVec = vec.clone().applyMatrix4(this.OCSInv.setPosition(ZeroVec));
|
||||
|
||||
if (dragType === DragPointType.Grip)
|
||||
{
|
||||
if (this.ContourCurve instanceof Polyline
|
||||
&& indexList.length === 1
|
||||
&& indexList[0] % 2 === 1)
|
||||
{
|
||||
let param = indexList[0] / 2;
|
||||
if (this.ContourCurve.GetBuilgeAt(Math.floor(param)) === 0)
|
||||
{
|
||||
let der = this.ContourCurve.GetFistDeriv(param).normalize();
|
||||
[der.x, der.y] = [der.y, -der.x];
|
||||
let d = localVec.dot(der);
|
||||
localVec.copy(der).multiplyScalar(d);
|
||||
}
|
||||
}
|
||||
this.ContourCurve.MoveGripPoints(indexList, localVec);
|
||||
}
|
||||
else
|
||||
this.ContourCurve.MoveStretchPoints(indexList, localVec);
|
||||
}
|
||||
GetGripPoints(): Array<Vector3>
|
||||
{
|
||||
return this.GetGripOrStretchPoints(DragPointType.Grip);
|
||||
}
|
||||
GetStretchPoints()
|
||||
{
|
||||
return this.GetGripOrStretchPoints(DragPointType.Stretch);
|
||||
}
|
||||
MoveGripPoints(indexList: number[], vec: Vector3)
|
||||
{
|
||||
this.MoveGripOrStretchPoints(indexList, vec, DragPointType.Grip)
|
||||
}
|
||||
MoveStretchPoints(indexList: Array<number>, vec: Vector3)
|
||||
{
|
||||
this.MoveGripOrStretchPoints(indexList, vec, DragPointType.Stretch);
|
||||
}
|
||||
InitDrawObject(renderType: RenderType = RenderType.Wireframe)
|
||||
{
|
||||
if (renderType === RenderType.Wireframe)
|
||||
{
|
||||
return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex))
|
||||
}
|
||||
else if (renderType === RenderType.Conceptual || renderType === RenderType.Physical)
|
||||
{
|
||||
return new Object3D().add(
|
||||
new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)),
|
||||
new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(7))
|
||||
);
|
||||
}
|
||||
else if (renderType === RenderType.Jig)
|
||||
{
|
||||
return new Object3D().add(...FastWireframe2(this));
|
||||
}
|
||||
}
|
||||
UpdateDrawObject(renderType: RenderType, obj: Object3D)
|
||||
{
|
||||
DisposeThreeObj(obj);
|
||||
this._EdgeGeometry = undefined;
|
||||
this._MeshGeometry = undefined;
|
||||
this.MeshGeometry;
|
||||
|
||||
if (renderType === RenderType.Wireframe)
|
||||
{
|
||||
let l = obj as LineSegments;
|
||||
l.geometry = this.EdgeGeometry;
|
||||
l.material = ColorMaterial.GetLineMaterial(this.ColorIndex);
|
||||
}
|
||||
else if (renderType === RenderType.Conceptual || renderType === RenderType.Physical)
|
||||
{
|
||||
return obj.add(
|
||||
new Mesh(this.MeshGeometry, ColorMaterial.GetConceptualMaterial(this.ColorIndex)),
|
||||
new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(7))
|
||||
);
|
||||
}
|
||||
else if (renderType === RenderType.Jig)
|
||||
{
|
||||
obj.add(...FastWireframe2(this));
|
||||
}
|
||||
}
|
||||
ReadFile(file: CADFiler)
|
||||
{
|
||||
super.ReadFile(file);
|
||||
let ver = file.Read();
|
||||
this._contourCurve = file.ReadObject() as ExtureContourCurve;
|
||||
this._knifeRadius = file.Read();
|
||||
this.Update();
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFiler)
|
||||
{
|
||||
super.WriteFile(file);
|
||||
file.Write(1);
|
||||
file.WriteObject(this._contourCurve);
|
||||
file.Write(this._knifeRadius);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
import { Factory } from '../CADFactory';
|
||||
import { Entity } from '../Entity/Entity';
|
||||
import { AutoRecord } from '../AutoRecord';
|
||||
import { ObjectId } from '../ObjectId';
|
||||
import { CADFiler } from '../CADFiler';
|
||||
|
||||
@Factory
|
||||
export class Hole extends Entity
|
||||
{
|
||||
@AutoRecord FId: ObjectId;
|
||||
@AutoRecord MId: ObjectId;
|
||||
protected _Height: number;
|
||||
get Height()
|
||||
{
|
||||
return this._Height;
|
||||
}
|
||||
set Height(v: number)
|
||||
{
|
||||
if (this._Height !== v)
|
||||
{
|
||||
this.WriteAllObjectRecord();
|
||||
this._Height = v;
|
||||
this.Update();
|
||||
}
|
||||
}
|
||||
protected _ReadFile(file: CADFiler)
|
||||
{
|
||||
super._ReadFile(file);
|
||||
let ver = file.Read();//1
|
||||
if (ver <= 4)
|
||||
{
|
||||
//临时兼容旧图纸排钻,更新旧图纸后去掉兼容代码
|
||||
file['readIndex']--;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._Height = file.Read();
|
||||
this.FId = file.ReadSoftObjectId();
|
||||
this.MId = file.ReadSoftObjectId();
|
||||
}
|
||||
|
||||
}
|
||||
WriteFile(file: CADFiler)
|
||||
{
|
||||
super.WriteFile(file);
|
||||
file.Write(5);//ver
|
||||
file.Write(this._Height);
|
||||
file.WriteSoftObjectId(this.FId);
|
||||
file.WriteSoftObjectId(this.MId);
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import { Factory } from '../CADFactory';
|
||||
import { Entity } from '../Entity/Entity';
|
||||
|
||||
@Factory
|
||||
export class Solid3D extends Entity
|
||||
{
|
||||
}
|
@ -0,0 +1,236 @@
|
||||
import { Button, Card, Checkbox, Classes, ContextMenu, Intent, Menu, MenuItem, Popover, Position } from '@blueprintjs/core';
|
||||
import { IObservableValue } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { app } from '../../../ApplicationServices/Application';
|
||||
import { CURRENT_HOST, TemplateUrls } from '../../../Common/HostUrl';
|
||||
import { MouseKey } from '../../../Common/KeyEnum';
|
||||
import { PostJson, RequestStatus } from '../../../Common/Request';
|
||||
import { deflate, ExtrudeDrillFileIn, GetEntitysLogo, inflate } from '../../../Common/SerializeMaterial';
|
||||
import { CADFiler } from '../../../DatabaseServices/CADFiler';
|
||||
import { ExtrudeSolid } from '../../../DatabaseServices/Entity/Extrude';
|
||||
import { TempEditor } from '../../../Editor/TempEditor';
|
||||
import { IDirectoryProps } from '../SourceManage/CommonPanel';
|
||||
import { AppToaster } from '../Toaster';
|
||||
import { DrillingTemplateManage } from './DrillingTemplateManage';
|
||||
import { ModalPosition } from './ModalsManage';
|
||||
import { ExtrudeHole } from '../../../DatabaseServices/3DSolid/ExtrudeHole';
|
||||
import { appCache } from '../../../Common/AppCache';
|
||||
import { StoreageKeys } from '../../../Common/StoreageKeys';
|
||||
|
||||
export interface IDrillTempListProps
|
||||
{
|
||||
deleteFun?: (temp: { module_id; }) => void;
|
||||
dataList?: any[];
|
||||
select?: (e: React.FormEvent<HTMLInputElement>, data: any) => void;
|
||||
isRename: IObservableValue<boolean>;
|
||||
updata: (name: string, dir: IDirectoryProps, call: Function) => void;
|
||||
getData?: () => void;
|
||||
info: { id: string; name: string; };
|
||||
}
|
||||
|
||||
@observer
|
||||
export class DrillingTemplateList extends React.Component<IDrillTempListProps, { isContextMenuOpen: boolean; }> {
|
||||
private _cameraFiler: CADFiler;
|
||||
constructor(props)
|
||||
{
|
||||
super(props);
|
||||
this.state = {
|
||||
isContextMenuOpen: false
|
||||
};
|
||||
}
|
||||
private renderToasterMessage = () =>
|
||||
{
|
||||
return (
|
||||
<div className="flex-between toaster-message">
|
||||
<span>正在编辑排钻模板</span>
|
||||
<div>
|
||||
<Button text="保存" minimal onClick={this.handleUpdateTemp} />
|
||||
<Button text="取消" minimal onClick={() =>
|
||||
{
|
||||
AppToaster.clear();
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
public render()
|
||||
{
|
||||
return (
|
||||
<ul
|
||||
className="mat-list"
|
||||
>
|
||||
{
|
||||
this.props.dataList.map(temp =>
|
||||
{
|
||||
return (
|
||||
<li
|
||||
key={temp.module_id}
|
||||
data-id={temp.module_id}
|
||||
onMouseDown={(e) => this.handleMounseDown(e, temp)}
|
||||
style={{
|
||||
background: this.props.info.id === temp.module_id && "rgba(162, 186, 197, 0.34)",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<img src={`${CURRENT_HOST}/${temp.logo}`} />
|
||||
</div>
|
||||
<p title={temp.name}>{temp.name}</p>
|
||||
<Popover
|
||||
position={Position.RIGHT}
|
||||
onOpening={node => node.parentElement.parentElement.style.zIndex = "33"}
|
||||
content={
|
||||
<Card>
|
||||
<p>确认删除文件</p>
|
||||
<div>
|
||||
<Button style={{ marginRight: 10 }}
|
||||
className={Classes.POPOVER_DISMISS}
|
||||
text="取消" />
|
||||
<Button
|
||||
className={Classes.POPOVER_DISMISS}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={() => this.props.deleteFun(temp)}
|
||||
text="确定" />
|
||||
</div>
|
||||
</Card>
|
||||
}
|
||||
target={<Button
|
||||
icon="cross"
|
||||
minimal
|
||||
/>}
|
||||
/>
|
||||
<Checkbox
|
||||
className={temp.isChecked && "selected"}
|
||||
inline={true}
|
||||
checked={temp.isChecked}
|
||||
onChange={e =>
|
||||
{
|
||||
this.props.select(e, temp);
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
private handleMounseDown = (e: React.MouseEvent<HTMLElement>, temp: any) =>
|
||||
{
|
||||
this.props.info.id = temp.module_id;
|
||||
this.props.info.name = temp.name;
|
||||
if (e.button === MouseKey.Right)
|
||||
{
|
||||
this.showContextMenu(e, temp);
|
||||
}
|
||||
};
|
||||
|
||||
//展示右键菜单
|
||||
private showContextMenu = (e: React.MouseEvent<HTMLElement>, temp: { module_id: string; }) =>
|
||||
{
|
||||
ContextMenu.show(
|
||||
<Menu>
|
||||
<MenuItem
|
||||
icon="comment"
|
||||
text="重命名"
|
||||
onClick={() => this.props.isRename.set(true)}
|
||||
/>
|
||||
<MenuItem
|
||||
icon="edit"
|
||||
text="编辑"
|
||||
onClick={() => this.startEditorTopline(temp)}
|
||||
/>
|
||||
</Menu>,
|
||||
{ left: e.clientX, top: e.clientY },
|
||||
() => this.setState({ isContextMenuOpen: false }),
|
||||
);
|
||||
this.setState({ isContextMenuOpen: true });
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
};
|
||||
private startEditorTopline = async (temp: { module_id: string; }) =>
|
||||
{
|
||||
TempEditor.Start();
|
||||
app.Editor.ModalManage.Clear();
|
||||
|
||||
let data = await PostJson(TemplateUrls.detail, { module_id: temp.module_id });
|
||||
|
||||
if (data.err_code === RequestStatus.Ok)
|
||||
{
|
||||
let files = JSON.parse(inflate(data.modules.file));
|
||||
let ens = files.map(ExtrudeDrillFileIn) as ExtrudeSolid[];
|
||||
ens.forEach(e => app.Database.ModelSpace.Append(e));
|
||||
|
||||
this._cameraFiler = new CADFiler;
|
||||
app.Viewer.CameraCtrl.WriteFile(this._cameraFiler);
|
||||
app.Viewer.ZoomAll();
|
||||
AppToaster.show({
|
||||
message: this.renderToasterMessage(),
|
||||
intent: Intent.PRIMARY,
|
||||
timeout: 0,
|
||||
onDismiss: this.exitEditor
|
||||
});
|
||||
}
|
||||
};
|
||||
private exitEditor = () =>
|
||||
{
|
||||
if (!this._cameraFiler) return;
|
||||
app.Viewer.CameraCtrl.ReadFile(this._cameraFiler);
|
||||
TempEditor.End();
|
||||
this._cameraFiler = undefined;
|
||||
app.Editor.SelectCtrl.Cancel();
|
||||
app.Editor.ModalManage.RenderModal(DrillingTemplateManage, ModalPosition.Old, {});
|
||||
};
|
||||
handleUpdateTemp = async () =>
|
||||
{
|
||||
await app.Editor.ModalManage.EndExecingCmd();
|
||||
let ens = app.Viewer.VisibleEntitys.filter(en => en instanceof ExtrudeHole) as ExtrudeHole[];
|
||||
if (ens.length > 0)
|
||||
{
|
||||
let module_id = this.props.info.id;
|
||||
let logo = await GetEntitysLogo(ens);
|
||||
|
||||
let dataList = [];
|
||||
//基点移动到基点
|
||||
for (let en of ens)
|
||||
{
|
||||
let vf = new CADFiler();
|
||||
en.WriteFile(vf);
|
||||
dataList.push(vf.Data);
|
||||
}
|
||||
let filesJson = JSON.stringify(dataList);
|
||||
let data = await PostJson(TemplateUrls.update, {
|
||||
module_id,
|
||||
logo,
|
||||
file: deflate(filesJson),
|
||||
zip_type: "gzip",
|
||||
});
|
||||
|
||||
AppToaster.clear();
|
||||
if (data.err_code === RequestStatus.Ok)
|
||||
{
|
||||
//更新缓存的自定义排钻实体
|
||||
ens = [];
|
||||
for (let file of dataList)
|
||||
ens.push(ExtrudeDrillFileIn(file));
|
||||
appCache.set(StoreageKeys.DrillTemp + module_id, ens);
|
||||
await this.props.getData();
|
||||
AppToaster.show({
|
||||
message: "排钻模板修改成功",
|
||||
timeout: 1500,
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "修改失败,可能当前图上不存在排钻实体,请重试或者取消",
|
||||
timeout: 1200,
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
import { Button, Classes, Icon, Intent, MenuItem } from '@blueprintjs/core';
|
||||
import { observable } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { app } from '../../../ApplicationServices/Application';
|
||||
import { TemplateUrls } from '../../../Common/HostUrl';
|
||||
import { DirectoryId, PostJson, RequestStatus, IResponseData } from '../../../Common/Request';
|
||||
import { deflate, ExtrudeDrillFileIn, GetEntitysLogo, inflate } from '../../../Common/SerializeMaterial';
|
||||
import { CADFiler } from '../../../DatabaseServices/CADFiler';
|
||||
import { CommandWrap } from '../../../Editor/CommandMachine';
|
||||
import { PromptStatus } from '../../../Editor/PromptResult';
|
||||
import { MoveMatrix } from '../../../Geometry/GeUtils';
|
||||
import { CommonPanel, IDirectoryProps } from '../SourceManage/CommonPanel';
|
||||
import { HandleDirComponent } from '../SourceManage/HandleDirComponent';
|
||||
import { AppToaster } from '../Toaster';
|
||||
import { DrillingTemplateList } from './DrillingTemplateList';
|
||||
import { ExtrudeHole } from '../../../DatabaseServices/3DSolid/ExtrudeHole';
|
||||
|
||||
@observer
|
||||
export class DrillingTemplateManage extends React.Component<{}> {
|
||||
private canCreateTemplate = observable.box(false);
|
||||
@observable private currentInfo = { id: "", name: "" };
|
||||
renderNav = () =>
|
||||
{
|
||||
return (
|
||||
<Button
|
||||
icon="cloud-upload"
|
||||
style={{
|
||||
marginRight: 10
|
||||
}}
|
||||
text="添加排钻模板"
|
||||
intent={Intent.SUCCESS}
|
||||
onClick={this.startCreateDrillingTemp}
|
||||
/>
|
||||
)
|
||||
}
|
||||
renderMenuItems = () =>
|
||||
{
|
||||
return (
|
||||
<MenuItem icon="cloud-upload" text="创建排钻模板"
|
||||
onClick={this.startCreateDrillingTemp}
|
||||
/>
|
||||
)
|
||||
}
|
||||
public render()
|
||||
{
|
||||
return (
|
||||
|
||||
<div
|
||||
className={Classes.DIALOG_CONTAINER}
|
||||
id="commonModal"
|
||||
>
|
||||
<div className={Classes.DIALOG + " topline drill-temp"}>
|
||||
<div
|
||||
className={Classes.DIALOG_HEADER}
|
||||
data-id="dragArea"
|
||||
>
|
||||
<Icon icon="bold" iconSize={18} />
|
||||
<h4 className="bp3-heading">排钻模板</h4>
|
||||
<Button
|
||||
aria-label="Close"
|
||||
minimal
|
||||
icon="cross"
|
||||
className={Classes.DIALOG_CLOSE_BUTTON}
|
||||
onClick={() => app.Editor.ModalManage.Clear()}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={Classes.DIALOG_BODY}
|
||||
>
|
||||
<CommonPanel
|
||||
defaultDirId={DirectoryId.DrillingDir}
|
||||
renderMenuItems={this.renderMenuItems}
|
||||
renderNav={this.renderNav}
|
||||
getUrl={TemplateUrls.list}
|
||||
deleteUrl={TemplateUrls.delete}
|
||||
clickTree={() =>
|
||||
{
|
||||
this.currentInfo.id = "";
|
||||
}}
|
||||
maxDirLength={0}
|
||||
>
|
||||
<DrillingTemplateList
|
||||
isRename={this.canCreateTemplate}
|
||||
updata={this.handleCreateTemplate}
|
||||
info={this.currentInfo}
|
||||
/>
|
||||
{
|
||||
this.canCreateTemplate.get() && <HandleDirComponent
|
||||
defualtValue={this.currentInfo.name}
|
||||
isReset={false}
|
||||
isOpen={this.canCreateTemplate}
|
||||
handleFunc={this.handleTemplate}
|
||||
title="输入排钻名称"
|
||||
/>
|
||||
}
|
||||
</CommonPanel>
|
||||
</div>
|
||||
<div className={Classes.DIALOG_FOOTER} >
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<Button
|
||||
className={Classes.INTENT_SUCCESS}
|
||||
text="预览"
|
||||
disabled={!this.currentInfo.id}
|
||||
onClick={() => this.drawTemplate(this.currentInfo.id)}
|
||||
/>
|
||||
<Button
|
||||
className={Classes.INTENT_DANGER}
|
||||
text="取消"
|
||||
onClick={() => app.Editor.ModalManage.Clear()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
handleTemplate = async (name: string, currentDir, callback: Function) =>
|
||||
{
|
||||
if (!name.trim())
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "名称不能为空",
|
||||
intent: Intent.DANGER,
|
||||
timeout: 1000
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.currentInfo.id)
|
||||
{
|
||||
await this.handleRenameTemp(name);
|
||||
await callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!currentDir)
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "未知错误,请重试",
|
||||
timeout: 1000
|
||||
});
|
||||
return;
|
||||
}
|
||||
CommandWrap(async () =>
|
||||
{
|
||||
await this.handleCreateTemplate(name, currentDir, callback);
|
||||
}, "_uploaddrilling")
|
||||
}
|
||||
}
|
||||
private handleCreateTemplate = async (name: string, currentDir: IDirectoryProps, callback: Function) =>
|
||||
{
|
||||
app.Editor.ModalManage.ToggleShow();
|
||||
app.Editor.MaskManage.Clear();
|
||||
|
||||
const reset = () =>
|
||||
{
|
||||
app.Editor.ModalManage.ToggleShow();
|
||||
app.Editor.MaskManage.ShowMask();
|
||||
this.canCreateTemplate.set(false);
|
||||
}
|
||||
|
||||
let enRes = await app.Editor.GetSelection({
|
||||
Msg: "排钻模板组件",
|
||||
Filter: {
|
||||
filterTypes: [ExtrudeHole],
|
||||
},
|
||||
});
|
||||
if (enRes.Status !== PromptStatus.OK)
|
||||
{
|
||||
reset();
|
||||
return;
|
||||
};
|
||||
|
||||
let ens = enRes.SelectSet.SelectEntityList.map(e => e.Clone()) as ExtrudeHole[];
|
||||
|
||||
let ptRes = await app.Editor.GetPoint({
|
||||
Msg: "指定基点"
|
||||
})
|
||||
|
||||
if (ptRes.Status !== PromptStatus.OK)
|
||||
{
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
let logo = await GetEntitysLogo(ens);
|
||||
|
||||
let dataList = [];
|
||||
//基点移动到基点
|
||||
for (let en of ens)
|
||||
{
|
||||
let vf = new CADFiler();
|
||||
en.ApplyMatrix(MoveMatrix(ptRes.Point.negate()));
|
||||
en.WriteFile(vf);
|
||||
dataList.push(vf.Data);
|
||||
}
|
||||
|
||||
let fileJson = JSON.stringify(dataList);
|
||||
|
||||
let data = await PostJson(TemplateUrls.create, {
|
||||
dir_id: currentDir.id,
|
||||
name,
|
||||
logo,
|
||||
file: deflate(fileJson),
|
||||
zip_type: "gzip",
|
||||
});
|
||||
|
||||
if (data.err_code === RequestStatus.Ok)
|
||||
{
|
||||
await callback();
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
handleRenameTemp = async (name: string) =>
|
||||
{
|
||||
let data = await PostJson(TemplateUrls.update, {
|
||||
module_id: this.currentInfo.id,
|
||||
name
|
||||
});
|
||||
if (data.err_code === RequestStatus.Ok)
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "重命名成功",
|
||||
timeout: 1000
|
||||
})
|
||||
}
|
||||
this.canCreateTemplate.set(false);
|
||||
}
|
||||
private drawTemplate = async (module_id: string) =>
|
||||
{
|
||||
app.Editor.ModalManage.Clear();
|
||||
|
||||
let data = await PostJson(TemplateUrls.detail, { module_id });
|
||||
|
||||
if (data.err_code === RequestStatus.Ok)
|
||||
{
|
||||
let modules = JSON.parse(inflate(data.modules.file));
|
||||
for (let module of modules)
|
||||
{
|
||||
app.Database.ModelSpace.Append(ExtrudeDrillFileIn(module));
|
||||
}
|
||||
app.Editor.UpdateScreen();
|
||||
}
|
||||
}
|
||||
private startCreateDrillingTemp = () =>
|
||||
{
|
||||
this.currentInfo.id = "";
|
||||
this.currentInfo.name = "";
|
||||
this.canCreateTemplate.set(true);
|
||||
}
|
||||
}
|
Loading…
Reference in new issue