!166 双击多段线

Merge pull request !166 from ZoeLeeFZ/dbclickPl
pull/166/MERGE
ChenX 6 years ago
parent 7ea9f0a093
commit 6052844c2c

@ -83,6 +83,13 @@ export class Entity extends CADObject
return new Vector3().setFromMatrixPosition(this.m_Matrix); return new Vector3().setFromMatrixPosition(this.m_Matrix);
} }
set Position(v: Vector3)
{
this.WriteAllObjectRecord();
this.m_Matrix.setPosition(v);
this.Update();
}
get OCSInv(): Matrix4 get OCSInv(): Matrix4
{ {
return new Matrix4().getInverse(this.m_Matrix); return new Matrix4().getInverse(this.m_Matrix);

@ -1,8 +1,7 @@
import { AdditiveBlending, BufferGeometry, Float32BufferAttribute, Geometry, Object3D, Points, PointsMaterial, TextureLoader, Vector3 } from "three"; import { AdditiveBlending, BufferGeometry, Float32BufferAttribute, Object3D, Points, PointsMaterial, TextureLoader, Vector3 } from "three";
import { MoveMatrix } from "../Geometry/GeUtils"; import { MoveMatrix } from "../Geometry/GeUtils";
import { RenderType } from "../GraphicsSystem/Enum"; import { RenderType } from "../GraphicsSystem/Enum";
import { Factory } from "./CADFactory"; import { Factory } from "./CADFactory";
import { CADFile } from "./CADFile";
import { Entity } from "./Entity"; import { Entity } from "./Entity";
let pointMaterial: PointsMaterial; let pointMaterial: PointsMaterial;
@ -28,11 +27,10 @@ LoadPointMaterial();
@Factory @Factory
export class Point extends Entity export class Point extends Entity
{ {
private m_Position: Vector3;
constructor(position: Vector3 = new Vector3()) constructor(position: Vector3 = new Vector3())
{ {
super(); super();
this.m_Position = position; this.m_Matrix.setPosition(position);
} }
/** /**
@ -46,33 +44,13 @@ export class Point extends Entity
protected InitDrawObject(renderType: RenderType = RenderType.Wireframe): Object3D protected InitDrawObject(renderType: RenderType = RenderType.Wireframe): Object3D
{ {
let geometry = new BufferGeometry(); let geometry = new BufferGeometry();
geometry.addAttribute("position", new Float32BufferAttribute(this.m_Position.toArray(), 3)); geometry.addAttribute("position", new Float32BufferAttribute([0, 0, 0], 3));
return new Points(geometry, LoadPointMaterial()); return new Points(geometry, LoadPointMaterial());
} }
private UpdateGeometry(geometry: Geometry)
{
}
/**
* ,,
*
* @param {RenderType} type
* @param {Object3D} en
* @memberof Entity
*/
UpdateDrawObject(type: RenderType, en: Object3D)
{
}
GetSnapPoints(): Array<Vector3> GetSnapPoints(): Array<Vector3>
{ {
return [this.m_Position.clone().applyMatrix4(this.OCS)]; return [this.Position];
} }
MoveSnapPoints(indexList: number[], vec: Vector3) MoveSnapPoints(indexList: number[], vec: Vector3)
{ {
if (indexList.length === 1) if (indexList.length === 1)
@ -98,21 +76,4 @@ export class Point extends Entity
{ {
this.MoveSnapPoints(indexList, vec); this.MoveSnapPoints(indexList, vec);
} }
//#region -------------------------File-------------------------
//对象从文件中读取数据,初始化自身
ReadFile(file: CADFile)
{
let ver = file.Read();
super.ReadFile(file);
this.m_Position.fromArray(file.Read());
}
//对象将自身数据写入到文件.
WriteFile(file: CADFile)
{
file.Write(1);
super.WriteFile(file);
file.Write(this.m_Position.toArray());
}
} }

@ -102,11 +102,22 @@ export class Polyline extends Curve
{ {
if (index < this.m_LineData.length) if (index < this.m_LineData.length)
{ {
this.WriteAllObjectRecord();
this.m_LineData.splice(index, 1); this.m_LineData.splice(index, 1);
this.Update(); this.Update();
} }
return this; return this;
} }
RemoveVertexIn(from: number, to: number): this
{
if (from + 1 < this.m_LineData.length && to > from)
{
this.WriteAllObjectRecord();
this.m_LineData.splice(from + 1, to - from - 1);
this.Update();
}
return this;
}
GetPoint2dAt(index: number): Vector2 | undefined GetPoint2dAt(index: number): Vector2 | undefined
{ {
if (index >= 0 && this.m_LineData.length > index) if (index >= 0 && this.m_LineData.length > index)

@ -6,12 +6,14 @@ import { RenderType } from '../GraphicsSystem/Enum';
import { Factory } from './CADFactory'; import { Factory } from './CADFactory';
import { CADFile } from './CADFile'; import { CADFile } from './CADFile';
import { Curve } from './Curve'; import { Curve } from './Curve';
import { equalv3 } from '../Geometry/GeUtils';
@Factory @Factory
export class Spline extends Curve export class Spline extends Curve
{ {
private m_PointList: Vector3[]; private m_PointList: Vector3[];
private m_ClosedMark: boolean = false;
constructor(points?: Vector3[]) constructor(points?: Vector3[])
{ {
super(); super();
@ -28,6 +30,22 @@ export class Spline extends Curve
this.m_PointList = v; this.m_PointList = v;
this.Update(); this.Update();
} }
//闭合标志
get CloseMark(): boolean
{
return this.m_ClosedMark;
}
//曲线是否闭合
get IsClose(): boolean
{
return this.CloseMark || (equalv3(this.StartPoint, this.EndPoint, 1e-4)) && this.EndParam > 1;
}
set CloseMark(v: boolean)
{
this.WriteAllObjectRecord();
this.m_ClosedMark = v;
this.Update()
}
get StartPoint() get StartPoint()
{ {
return this.m_PointList[0]; return this.m_PointList[0];
@ -46,11 +64,11 @@ export class Spline extends Curve
} }
GetSnapPoints() GetSnapPoints()
{ {
return this.m_PointList return this.m_PointList.map(p => p.clone().applyMatrix4(this.OCS));
} }
GetStretchPoints() GetStretchPoints()
{ {
return this.m_PointList; return this.GetSnapPoints();
} }
MoveSnapPoints(indexList: Array<number>, vec: Vector3) MoveSnapPoints(indexList: Array<number>, vec: Vector3)
{ {
@ -83,7 +101,10 @@ export class Spline extends Curve
let spl = en as THREE.Line; let spl = en as THREE.Line;
let geo = spl.geometry as Geometry; let geo = spl.geometry as Geometry;
geo.dispose(); geo.dispose();
if (this.CloseMark && !equalv3(this.m_PointList[0], arrayLast(this.m_PointList)))
{
this.m_PointList.push(this.m_PointList[0].clone());
}
let curve = new THREE.CatmullRomCurve3(this.Points); let curve = new THREE.CatmullRomCurve3(this.Points);
spl.geometry = new Geometry().setFromPoints(curve.getPoints(this.Points.length * 10)); spl.geometry = new Geometry().setFromPoints(curve.getPoints(this.Points.length * 10));
geo.verticesNeedUpdate = true; geo.verticesNeedUpdate = true;

@ -1,44 +0,0 @@
import { PointPick } from "./PointPick";
import { PointLight } from "../DatabaseServices/PointLight";
import { app } from "../ApplicationServices/Application";
import { LightModal } from "../UI/Components/Modal/LightModal";
import { ModalPosition } from "../UI/Components/Modal/ModalsManage";
import { Text } from "../DatabaseServices/Text/Text";
import { Board } from "../DatabaseServices/Board";
import { BoardOptionModal } from "../UI/Components/Board/BoardOptionModal";
import { Singleton } from "../Common/Singleton";
import { TextArea } from "../DatabaseServices/Text/TextArea";
import { Entity } from "../DatabaseServices/Entity";
export class DbClickManager
{
OnDbClick()
{
let en = PointPick(app.m_Editor.m_MouseCtrl.m_CurMousePointVCS, app.m_Viewer)[0];
//防止双击到Jig对象
if (!en || !en.userData
|| !(en.userData instanceof Entity)
|| !en.userData.Id)
return;
//双击实体取消选中状态
app.m_Editor.m_SelectCtrl.Cancel();
if (en.userData instanceof PointLight)
{
app.m_Editor.m_ModalManage.RenderModeless(LightModal, ModalPosition.Right, { selectedObj: en.userData });
}
else if (en.userData instanceof Text)
{
let textarea = Singleton.GetInstance(TextArea);
textarea.StartEditorText(en);
}
else if (en.userData instanceof Board)
{
app.m_Editor.m_ModalManage.RenderModeless(
BoardOptionModal,
ModalPosition.Right,
{ board: en.userData }
);
}
}
}

@ -0,0 +1,386 @@
import { app } from "../../ApplicationServices/Application";
import { arraySortByNumber } from "../../Common/ArrayExt";
import { curveLinkGroup, Vec3DTo2D } from "../../Common/CurveUtils";
import { KeyWord } from "../../Common/InputState";
import { Curve } from "../../DatabaseServices/Curve";
import { Point } from "../../DatabaseServices/Point";
import { Polyline, PolylineProps } from "../../DatabaseServices/Polyline";
import { Spline } from "../../DatabaseServices/Spline";
import { equaln, equalv3 } from "../../Geometry/GeUtils";
import { Jig } from "../Jig";
import { PromptStatus } from "../PromptResult";
import { log } from "../../Common/Utils";
interface IVertex
{
index: number;
point: Point;
}
export class DBClickPolyline
{
private entity: Curve;
HandlePolyline = async (pl: Polyline) =>
{
this.entity = pl;
//默认关键字列表
const defaultKW: KeyWord[] = [
{ key: "C", msg: "闭合" },
{ key: "J", msg: "合并" },
{ key: "E", msg: "编辑顶点" },
// { key: "F", msg: "拟合" },
// { key: "S", msg: "样条曲线" },
{ key: "D", msg: "非曲线化" },
{ key: "R", msg: "反转" },
{ key: "U", msg: "放弃" }
];
//操作记录数,用于撤销双击后的操作
let totalRecCount = 0;
while (true)
{
let pl = this.entity as Polyline;
defaultKW[0].key = pl.CloseMark ? "O" : "C";
defaultKW[0].msg = pl.CloseMark ? "打开" : "闭合";
let res = await app.m_Editor.GetKeyWords({
Msg: "请输入选项",
KeyWordList: defaultKW
})
if (res.Status !== PromptStatus.Keyword)
return;
let execStatus = PromptStatus.OK;
switch (res.StringResult)
{
case "C": //闭合
app.m_Database.hm.StartCmd("");
totalRecCount++;
pl.CloseMark = true;
app.m_Database.hm.EndCmd();
break;
case "O": //打开
app.m_Database.hm.StartCmd("");
totalRecCount++;
pl.CloseMark = false;
app.m_Database.hm.EndCmd();
break;
case "J": //合并
if (!pl.CloseMark)
{
app.m_Database.hm.StartCmd("");
totalRecCount++;
execStatus = await this.Join();
app.m_Database.hm.EndCmd();
}
else
log("无法合并闭合多段线")
break;
case "E": //编辑顶点
execStatus = await this.EditorVertex();
Jig.Destroy();
break;
case "D": //非曲线化
totalRecCount++;
this.TransfromNonCurve();
break;
case "R": //反转
totalRecCount++;
app.m_Database.hm.StartCmd("");
pl.Reverse();
app.m_Database.hm.EndCmd();
break;
case "U": //放弃
if (totalRecCount > 0)
{
totalRecCount--;
app.m_Database.hm.Undo();
}
break;
}
app.m_Editor.UpdateScreen();
if (execStatus === PromptStatus.Cancel)
return;
}
}
private EditorVertex = async () =>
{
//编辑顶点关键字列表
const editeVertexKW: KeyWord[] = [
{ key: "N", msg: "下一个" },
{ key: "P", msg: "上一个" },
{ key: "B", msg: "打断" },
{ key: "I", msg: "插入" },
{ key: "M", msg: "移动" },
{ key: "S", msg: "拉直" },
// { key: "T", msg: "切向" },
{ key: "X", msg: "退出" },
];
//顶点位置
let vertex: IVertex = {
index: 0,
point: Jig.Draw(new Point(this.entity.StartPoint))
};
//存储前后顶点索引
let indexList: number[] = [];
while (true)
{
app.m_Editor.UpdateScreen();
let res = await app.m_Editor.GetKeyWords({
Msg: "输入顶点编辑选项",
KeyWordList: editeVertexKW
})
if (res.Status !== PromptStatus.Keyword)
{
return PromptStatus.Cancel;
}
let execStatus = PromptStatus.OK;
switch (res.StringResult)
{
case "N": //下一个顶点
this.ToggleVertex(vertex, true);
break;
case "P": //上一个
this.ToggleVertex(vertex, false);
break;
case "B": //打断
//存入第一个索引
indexList.push(vertex.index);
execStatus = await this.ExecEditor(vertex, indexList, "B");
break;
case "I": //插入
app.m_Database.hm.StartCmd("");
execStatus = await this.ChangeVertex(vertex, false);
app.m_Database.hm.EndCmd();
break;
case "M": //移动
app.m_Database.hm.StartCmd("");
execStatus = await this.ChangeVertex(vertex, true);
app.m_Database.hm.EndCmd();
break;
case "S": //拉直
indexList.push(vertex.index);
execStatus = await this.ExecEditor(vertex, indexList, "S");
break
case "X": //退出
return PromptStatus.None;
}
if (execStatus === PromptStatus.Cancel)
{
return PromptStatus.Cancel;
}
}
}
private ExecEditor = async (vertex: IVertex, indexList: number[], editorCommand: string) =>
{
//打断/拉直关键字列表
const execKW: KeyWord[] = [
{ key: "N", msg: "下一个" },
{ key: "P", msg: "上一个" },
{ key: "G", msg: "执行" },
{ key: "X", msg: "退出" }
];
while (true)
{
let res = await app.m_Editor.GetKeyWords({
Msg: "请输入选项",
KeyWordList: execKW
})
if (res.Status !== PromptStatus.Keyword)
{
return PromptStatus.Cancel;
}
switch (res.StringResult)
{
case "N": //下一个顶点
this.ToggleVertex(vertex, true);
break;
case "P": //上一个
this.ToggleVertex(vertex, false);
break;
case "G": //执行
this.ExecSAndBCommand(indexList, vertex, editorCommand);
case "X": //退出
return PromptStatus.None;
}
app.m_Editor.UpdateScreen();
}
}
private Join = async () =>
{
let pl = this.entity as Polyline;
let exSsRes = await app.m_Editor.GetSelection({
Msg: "请选择对象<全部选择>:",
Filter: { filterTypes: [Curve] }
});
if (exSsRes.Status === PromptStatus.Cancel)
return PromptStatus.Cancel;
let cus = exSsRes.SelectSet.SelectEntityList as Curve[];
if (!cus.includes(pl))
cus.push(pl);
let groups = curveLinkGroup(cus);
for (let g of groups)
{
if (!g.includes(pl))
continue;
for (let cu of g)
{
if (cu !== pl)
{
pl.Join(cu);
cu.Erase();
}
}
}
return PromptStatus.OK;
}
private ToggleVertex(vertex: IVertex, isNext: boolean)
{
let pl = this.entity as Polyline;
isNext ? vertex.index++ : vertex.index--;
if (vertex.index < 0)
vertex.index = 0;
else if (vertex.index > pl.EndParam)
vertex.index = pl.EndParam;
vertex.point.Position = pl.GetPointAtParam(vertex.index);
}
private Break(indexList: number[])
{
let pl = this.entity as Polyline;
let cus = pl.GetSplitCurves(indexList);
pl.Erase();
this.entity = null;
for (let cu of cus)
{
if (indexList.length === 2)
{
if (equalv3(cu.StartPoint, pl.GetPointAtParam(Math.min(...indexList))))
continue;
}
if (!this.entity) this.entity = cu;
app.m_Database.ModelSpace.Append(cu)
}
}
//改变顶点,移动或者插入
private ChangeVertex = async (vertex: IVertex, isMove: boolean) =>
{
let pl = this.entity as Polyline;
let ptRes = await app.m_Editor.GetPoint({
Msg: "为新顶点指定位置",
BasePoint: vertex.point.Position,
AllowDrawRubberBand: true
})
if (ptRes.Status === PromptStatus.Cancel)
return PromptStatus.Cancel;
let newPt = ptRes.Value.clone().applyMatrix4(pl.OCSInv);
if (isMove)
{
pl.SetPointAt(vertex.index, Vec3DTo2D(newPt));
}
else
{
vertex.index++
pl.AddVertexAt(vertex.index, Vec3DTo2D(newPt));
}
vertex.point.Position = ptRes.Value;
return PromptStatus.OK;
}
//拉直曲线
private StretchStraight(indexList: number[])
{
let pl = this.entity as Polyline;
arraySortByNumber(indexList);
pl.SetBulgeAt(indexList[0], 0);
if (indexList.length === 2)
pl.RemoveVertexIn(indexList[0], indexList[1]);
}
private ExecSAndBCommand(indexList: number[], vertex: IVertex, editorCommand: string)
{
app.m_Database.hm.StartCmd("");
if (!equaln(indexList[0], vertex.index))
indexList.push(vertex.index);
//执行并更新顶点信息
if (editorCommand === "B")
{
//执行打断操作
this.Break(indexList);
}
else
{
//执行拉直操作
this.StretchStraight(indexList);
}
vertex.index = indexList[0];
vertex.point.Position = this.entity.GetPointAtParam(indexList[0]);
app.m_Database.hm.EndCmd();
}
private TransfromNonCurve()
{
app.m_Database.hm.StartCmd("d");
let pl = this.entity;
if (pl instanceof Polyline)
{
for (let i = 0; i < pl.EndParam; i++)
{
let bul = pl.GetBuilgeAt(i);
if (bul !== 0)
pl.SetBulgeAt(i, 0);
}
}
else if (pl instanceof Spline)
{
let pts = pl.Points;
let data: PolylineProps[] = [];
for (let p of pts)
{
data.push({
pt: Vec3DTo2D(p),
bul: 0
})
}
pl.Erase();
this.entity = new Polyline(data);
app.m_Database.ModelSpace.Append(this.entity);
}
app.m_Database.hm.EndCmd();
}
private TransfromSpline()
{
app.m_Database.hm.StartCmd("s");
let pl = this.entity;
if (pl instanceof Polyline)
{
pl.Erase();
let pts = pl.GetStretchPoints();
let spl = new Spline(pts);
app.m_Database.ModelSpace.Append(spl);
spl.CloseMark = pl.CloseMark;
this.entity = spl;
}
app.m_Database.hm.EndCmd();
}
}

@ -0,0 +1,59 @@
import { app } from "../../ApplicationServices/Application";
import { Singleton } from "../../Common/Singleton";
import { Board } from "../../DatabaseServices/Board";
import { Entity } from "../../DatabaseServices/Entity";
import { PointLight } from "../../DatabaseServices/PointLight";
import { Polyline } from "../../DatabaseServices/Polyline";
import { Text } from "../../DatabaseServices/Text/Text";
import { TextArea } from "../../DatabaseServices/Text/TextArea";
import { BoardOptionModal } from "../../UI/Components/Board/BoardOptionModal";
import { LightModal } from "../../UI/Components/Modal/LightModal";
import { ModalPosition } from "../../UI/Components/Modal/ModalsManage";
import { PointPick } from "../PointPick";
import { DBClickPolyline } from "./DBClickPolyline";
import { commandMachine } from "../CommandMachine";
export class DbClickManager
{
OnDbClick = async () =>
{
let obj3d = PointPick(app.m_Editor.m_MouseCtrl.m_CurMousePointVCS, app.m_Viewer)[0];
//防止双击到Jig对象
if (!obj3d || !obj3d.userData
|| !(obj3d.userData instanceof Entity)
|| !obj3d.userData.Id)
return;
//双击实体取消选中状态
app.m_Editor.m_SelectCtrl.Cancel();
if (obj3d.userData instanceof PointLight)
{
app.m_Editor.m_ModalManage.RenderModeless(LightModal, ModalPosition.Right, { selectedObj: obj3d.userData });
}
else if (obj3d.userData instanceof Text)
{
let textarea = Singleton.GetInstance(TextArea);
textarea.StartEditorText(obj3d);
}
else if (obj3d.userData instanceof Board)
{
app.m_Editor.m_ModalManage.RenderModeless(
BoardOptionModal,
ModalPosition.Right,
{ board: obj3d.userData }
);
}
else if (obj3d.userData instanceof Polyline)
{
commandMachine.CommandStart("_pedit");
await Singleton.GetInstance(DBClickPolyline).HandlePolyline(obj3d.userData);
commandMachine.CommandEnd("_pedit");
}
else
{
//TODO:
}
}
}

@ -49,7 +49,7 @@ export class GetKeyWordsServices implements EditorService
this.m_Editor = ed; this.m_Editor = ed;
let container = document.createElement("div"); let container = document.createElement("div");
document.body.appendChild(container); document.getElementById("Webgl").appendChild(container);
ReactDOM.render( ReactDOM.render(
<Provider keywordStore={this}> <Provider keywordStore={this}>

@ -4,7 +4,7 @@ import { app } from '../ApplicationServices/Application';
import { InputState } from '../Common/InputState'; import { InputState } from '../Common/InputState';
import { Singleton } from '../Common/Singleton'; import { Singleton } from '../Common/Singleton';
import { Viewer } from '../GraphicsSystem/Viewer'; import { Viewer } from '../GraphicsSystem/Viewer';
import { DbClickManager } from './DbClick'; import { DbClickManager } from './DbClick/DbClick';
import { Editor } from './Editor'; import { Editor } from './Editor';

@ -45,10 +45,10 @@ export class KeyWordContextMenu extends React.Component<{ keywordStore?: GetKeyW
} }
}) })
} }
public render() public render()
{ {
let store = this.props.keywordStore; let store = this.props.keywordStore;
return ( return (
<Menu <Menu
style={ style={
@ -58,7 +58,8 @@ export class KeyWordContextMenu extends React.Component<{ keywordStore?: GetKeyW
position: "fixed", position: "fixed",
left: `${store.mousePositionX}px`, left: `${store.mousePositionX}px`,
top: `${store.mousePositionY}px`, top: `${store.mousePositionY}px`,
cursor: "default" cursor: "default",
zIndex: 25,
} }
} }
> >

Loading…
Cancel
Save