* 实现依赖收集,提前更新
* 实现模板倒角动作
* 测试模块旋转
* 修正旋转空间时的模版尺寸更新
* 使等分空间可用
* 实现旋转空间定位
* 加入设计说明和模版空间坐标系获取
* 重构变量定义和变量继承
* 实现DIV和POS变量
* 更新基础参数列表
* 相对定位的实现
* 增加模版切割类型
* 增加模版树更新
pull/411/MERGE
ChenX 5 years ago
parent 4637ed011c
commit 2fdae68905

@ -425,7 +425,7 @@ export class FilletUtils
}; };
} }
findNearestPt(pts: Vector3[], target: Vector3): Vector3 FindNearestPt(pts: Vector3[], target: Vector3): Vector3
{ {
let res = pts[0]; let res = pts[0];
let dis = Infinity; let dis = Infinity;
@ -455,7 +455,7 @@ export class FilletUtils
if (ipts.length > 2)//超过2个则有可能有多余交点 if (ipts.length > 2)//超过2个则有可能有多余交点
//找最近点 //找最近点
ipts = [this.findNearestPt(ipts, brResPt), this.findNearestPt(ipts, ptResPt)] ipts = [this.FindNearestPt(ipts, brResPt), this.FindNearestPt(ipts, ptResPt)]
if (ipts.length !== 2) if (ipts.length !== 2)
return "倒角失败!交点个数异常."; return "倒角失败!交点个数异常.";

@ -16,7 +16,7 @@ export class TemplateAction
if (this.parent) if (this.parent)
this.parent.WriteAllObjectRecord(); this.parent.WriteAllObjectRecord();
} }
Update(paramDiff: number | string) Update(paramDiff: number | string, newValue: number | string)
{ {
} }
//#region -------------------------File------------------------- //#region -------------------------File-------------------------

@ -0,0 +1,64 @@
import { Factory } from "../../CADFactory";
import { TemplateAction } from "./TemplateAction";
import { CADFiler } from "../../CADFiler";
import { ObjectId } from "../../ObjectId";
import { Board } from "../../Entity/Board";
import { FilletUtils } from "../../../Add-on/FilletUtils";
import { PromptEntityResult } from "../../../Editor/PromptResult";
import { Polyline } from "../../Entity/Polyline";
import { Circle } from "../../Entity/Circle";
@Factory
export class TemplateFilletAction extends TemplateAction
{
constructor(protected _FilletEntity?: ObjectId,
protected _CurveParam1?: number,
protected _CurveParam2?: number
)
{
super();
}
Update(paramDiff: number | string, newValue: number | string)
{
if (this._FilletEntity.IsErase) return;
let br = this._FilletEntity.Object as Board;
let cu = br.ContourCurve;
if (cu instanceof Circle)
return;
let fillet = new FilletUtils();
fillet.FilletRadius = newValue as number;
let p1 = cu.GetPointAtParam(this._CurveParam1);
let p2 = cu.GetPointAtParam(this._CurveParam2);
let res1 = new PromptEntityResult(cu, p1);
let res2 = new PromptEntityResult(cu, p2);
let fres = fillet.FilletPolyLineSelf(res1, res2);
if (fres)
br.ContourCurve = fres.cu1 as Polyline;
}
//#region -------------------------File-------------------------
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
//对象从文件中读取数据,初始化自身
ReadFile(file: CADFiler)
{
let ver = file.Read();
this._FilletEntity = file.ReadObjectId();
this._CurveParam1 = file.Read();
this._CurveParam2 = file.Read();
}
//对象将自身数据写入到文件.
WriteFile(file: CADFiler)
{
file.Write(1);
file.WriteObjectId(this._FilletEntity);
file.Write(this._CurveParam1);
file.Write(this._CurveParam2);
}
}

@ -1,33 +0,0 @@
import { app } from "../../../ApplicationServices/Application";
import { FixIndex } from "../../../Common/Utils";
import { TemplateRecord } from "../TemplateRecord";
import { GetDefaultTemplate } from "../TemplateTest";
export class TestTemplateAction
{
time;
exec()
{
if (this.time)
{
clearInterval(this.time);
this.time = undefined;
return;
}
let params = ["L", "W", "H"];
let paramIndex = 0;
let record = GetDefaultTemplate() as TemplateRecord;
let count = 1;
this.time = setInterval(() =>
{
count++;
if (count === 100)
{
count = 0;
paramIndex = FixIndex(paramIndex + 1, 3);
}
let param = record.GetParam(params[paramIndex]);
param.UpdateParam(Math.abs(count * 10 - 500));
app.Editor.UpdateScreen();
}, 16);
}
}

@ -5,6 +5,7 @@ import { CADFiler } from "../../CADFiler";
import { TemplateRecord } from "../TemplateRecord"; import { TemplateRecord } from "../TemplateRecord";
import { TemplateAction } from "../Action/TemplateAction"; import { TemplateAction } from "../Action/TemplateAction";
import { TemplateParamType } from "./TemplateParamType"; import { TemplateParamType } from "./TemplateParamType";
import { eval2 } from "../../../Common/eval";
/** /**
* *
@ -12,9 +13,15 @@ import { TemplateParamType } from "./TemplateParamType";
@Factory @Factory
export class TemplateParam export class TemplateParam
{ {
/**
*
* (js) `_`,`$`.
*/
@AutoRecord name: string; @AutoRecord name: string;
@AutoRecord expr: string; /** 表达式 使用js引起求值(暂时) */
@AutoRecord expr: string | number = "";
/** /**
* ,
* , UpdateParam * , UpdateParam
*/ */
@AutoRecord value: string | number; @AutoRecord value: string | number;
@ -55,6 +62,7 @@ export class TemplateParam
if (this.parent) if (this.parent)
this.parent.WriteAllObjectRecord(); this.parent.WriteAllObjectRecord();
} }
/** /**
* ,. * ,.
* ,`this.value = xxx;` * ,`this.value = xxx;`
@ -72,7 +80,7 @@ export class TemplateParam
{ {
let diff = newV - oldV; let diff = newV - oldV;
for (let a of this.actions) for (let a of this.actions)
a.Update(diff); a.Update(diff, newV);
this.value = newV; this.value = newV;
} }
break; break;
@ -82,6 +90,43 @@ export class TemplateParam
break; break;
} }
} }
/**
*
* @param vardefines
* @param paramMap .()
*/
EvalUpdate(vardefines: Object, paramMap: Map<string, TemplateParam>, evaled: Set<TemplateParam>, update = true): number
{
if (this.expr === "") return this.value as number;
if (evaled.has(this)) return this.value as number;
let value = parseFloat(this.expr as string);
if (isNaN(value))
{
//依赖收集 提前更新
let keywords = (<string>this.expr).split(/[\s(){}=+-/*/,%;]/).filter(s => s.length > 0);
for (let key of keywords)
{
if (key !== this.name && paramMap.has(key))
paramMap.get(key).EvalUpdate(vardefines, paramMap, evaled, update);
}
value = eval2(this.expr as string, vardefines);
}
else
this.expr = "";
vardefines[this.name] = value;
if (update)
this.UpdateParam(value);
evaled.add(this);
return value;
}
//#region -------------------------File------------------------- //#region -------------------------File-------------------------
//对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化 //对象应该实现dataIn和DataOut的方法,为了对象的序列化和反序列化
//对象从文件中读取数据,初始化自身 //对象从文件中读取数据,初始化自身

@ -12,15 +12,18 @@ export interface PositioningParam
count?: number; count?: number;
} }
/**
* ()
*/
@Factory @Factory
export class Positioning implements ISerialize export class Positioning implements ISerialize
{ {
SpaceCS: Matrix4;//空间坐标系 SpaceCS: Matrix4;//空间坐标系
SpaceBox: Box3;//有可能不存在
SpaceSize: Vector3;//有可能不存在 SpaceSize: Vector3;//有可能不存在
/** /**
* * ( SpaceCS SpaceBox SpaceSize)
*/ */
async Positioning(param?: PositioningParam) async Positioning(param?: PositioningParam)
{ {

@ -41,7 +41,8 @@ export class PositioningClampSpace extends Positioning
if (parse.m_ParseOK) if (parse.m_ParseOK)
{ {
this.SpaceCS = parse.m_SpaceOCS; this.SpaceCS = parse.m_SpaceOCS;
this.SpaceBox = parse.m_SpaceBox; let p = parse.m_SpaceBox.min.clone().applyMatrix4(this.SpaceCS);
this.SpaceCS.setPosition(p);
this.SpaceSize = parse.Size; this.SpaceSize = parse.Size;
} }
else else

@ -1,3 +1,4 @@
import { Matrix4, Vector3, Math, Box3 } from "three";
import { AutoRecord, ISPROXYKEY } from "../AutoRecord"; import { AutoRecord, ISPROXYKEY } from "../AutoRecord";
import { Factory } from "../CADFactory"; import { Factory } from "../CADFactory";
import { CADFiler } from "../CADFiler"; import { CADFiler } from "../CADFiler";
@ -8,16 +9,29 @@ import { SymbolTableRecord } from "../SymbolTableRecord";
import { TemplateParam } from "./Param/TemplateParam"; import { TemplateParam } from "./Param/TemplateParam";
import { TemplateParamType } from "./Param/TemplateParamType"; import { TemplateParamType } from "./Param/TemplateParamType";
import { Positioning } from "./Positioning/Positioning"; import { Positioning } from "./Positioning/Positioning";
import { TemplateType } from "./TemplateType"; import { TemplateSplitType, TemplateType } from "./TemplateType";
/** /**
* * ###
* ,, * ,,
*
* : L W H RX RY RZ X Y Z
* : _ $
*
* #### .
* expr,(value).,.
* ,expr.(valueexpr).
*
* `DIV`,`LWH`,()
*
* ,,(,)
*
*/ */
@Factory @Factory
export class TemplateRecord extends SymbolTableRecord export class TemplateRecord extends SymbolTableRecord
{ {
@AutoRecord Type: TemplateType; @AutoRecord Type: TemplateType;
@AutoRecord SplitType = TemplateSplitType.None;
@AutoRecord Parent: ObjectId; @AutoRecord Parent: ObjectId;
@AutoRecord Children: ObjectId[]; @AutoRecord Children: ObjectId[];
@AutoRecord Params: TemplateParam[]; @AutoRecord Params: TemplateParam[];
@ -27,63 +41,48 @@ export class TemplateRecord extends SymbolTableRecord
{ {
super(); super();
//监听 //监听
this.Params = new Proxy([], { this.Params = this.CreateProxyArray(
set: (target, key, value, receiver) => value =>
{ {
if (Reflect.get(target, key, receiver) !== value) if (value instanceof TemplateParam)
value.parent = this;
}
);
this.Objects = this.CreateProxyArray(
value =>
{
if (value instanceof ObjectId && value.Object instanceof Entity)
{ {
this.WriteAllObjectRecord(); if (!this.Id)
if (value instanceof TemplateParam) console.warn("请先加模版添加到Database后在进行操作!");
value.parent = this; value.Object.Template = this.Id;
} }
return Reflect.set(target, key, value, receiver);
},
get: (target, key, receiver) =>
{
if (key === ISPROXYKEY)
return true;
return Reflect.get(target, key, receiver);
} }
}); );
this.Objects = new Proxy([], {
set: (target, key, value, receiver) => this.Children = this.CreateProxyArray(
value =>
{ {
if (Reflect.get(target, key, receiver) !== value) if (value instanceof ObjectId && value.Object instanceof TemplateRecord)
{ {
if (this.WriteAllObjectRecord()) if (!this.Id)
{ console.warn("请先加模版添加到Database后在进行操作!");
if (value instanceof ObjectId && value.Object instanceof Entity) value.Object.Parent = this.Id;
{
if (!this.Id)
console.warn("请先加模版添加到Database后在进行操作!");
value.Object.Template = this.Id;
}
}
} }
return Reflect.set(target, key, value, receiver);
},
get: (target, key, receiver) =>
{
if (key === ISPROXYKEY)
return true;
return Reflect.get(target, key, receiver);
} }
}); );
}
this.Children = new Proxy([], { private CreateProxyArray(setCallback: (v: any) => void)
{
return new Proxy([], {
set: (target, key, value, receiver) => set: (target, key, value, receiver) =>
{ {
if (Reflect.get(target, key, receiver) !== value) if (Reflect.get(target, key, receiver) !== value)
{ {
if (this.WriteAllObjectRecord()) this.WriteAllObjectRecord();
{ setCallback(value);
if (value instanceof ObjectId && value.Object instanceof TemplateRecord)
{
if (!this.Id)
console.warn("请先加模版添加到Database后在进行操作!");
value.Object.Parent = this.Id;
}
}
} }
return Reflect.set(target, key, value, receiver); return Reflect.set(target, key, value, receiver);
}, },
@ -96,26 +95,40 @@ export class TemplateRecord extends SymbolTableRecord
}); });
} }
/** Traverse(callback: (arg0: this) => void)
*
*/
get NodeDepth()
{ {
let parent = this.Parent; callback(this);
let depth = 0; for (let c of this.Children)
while (parent)
{ {
depth++; let template = c.Object as TemplateRecord;
let template = parent.Object as TemplateRecord; template.Traverse(callback);
parent = template.Parent;
} }
return depth;
} }
private _NodeDepthCache: number;
/** 节点深度,根节点=0 */
get NodeDepth()
{
if (this._NodeDepthCache !== undefined)
return this._NodeDepthCache;
if (!this.Parent) return 0;
let parentTemplate = this.Parent.Object as TemplateRecord;
this._NodeDepthCache = parentTemplate.NodeDepth + 1;
return this._NodeDepthCache;
}
/** 模版定位 */
get Positioning(): Positioning get Positioning(): Positioning
{ {
return this.positioning; return this.positioning;
} }
/**
* ,使.
*/
set Positioning(p: Positioning) set Positioning(p: Positioning)
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
@ -123,14 +136,18 @@ export class TemplateRecord extends SymbolTableRecord
this.positioning = p; this.positioning = p;
} }
static SizeParamName = ["L", "W", "H"]; //#region param
InitSizeParams(length = 0, width = 0, height = 0)
static BaseParamName = ["L", "W", "H",
"PX", "PY", "PZ",
"RX", "RY", "RZ"];
/** 初始化基础参数 */
InitBaseParams()
{ {
let size = [length, width, height]; for (let paramName of TemplateRecord.BaseParamName)
for (let i = 0; i < 3; i++)
{ {
let paramName = TemplateRecord.SizeParamName[i]; let value = 0;
let value = size[i];
let param = new TemplateParam(); let param = new TemplateParam();
param.name = paramName; param.name = paramName;
param.type = TemplateParamType.Float; param.type = TemplateParamType.Float;
@ -140,148 +157,337 @@ export class TemplateRecord extends SymbolTableRecord
return this; return this;
} }
get LParam() get LParam() { return this.Params[0]; }
{ get WParam() { return this.Params[1]; }
return this.GetParam("L"); get HParam() { return this.Params[2]; }
}
get WParam() get PXParam() { return this.Params[3]; }
{ get PYParam() { return this.Params[4]; }
return this.GetParam("W"); get PZParam() { return this.Params[5]; }
}
get HParam() get RXParam() { return this.Params[6]; }
{ get RYParam() { return this.Params[7]; }
return this.GetParam("H"); get RZParam() { return this.Params[8]; }
}
UpdateAllTemplate(newParams: [])
{
for (let i = 0; i < this.Params.length; i++)
{
let oldParam = this.Params[i];
oldParam.UpdateParam(newParams[i]);
}
}
/**
*
* ,,
*/
UpdateParam(name: string, value: any, expr?: string) UpdateParam(name: string, value: any, expr?: string)
{ {
let param = this.GetParam(name); let param = this.GetParam(name);
if (param) if (param)
{
param.UpdateParam(value); param.UpdateParam(value);
}
} }
GetParam(paramName: string)
GetParam(paramName: string): TemplateParam | undefined
{ {
for (let param of this.Params) return this.Params.find(param => param.name === paramName);
{
if (param.name === paramName)
return param;
}
} }
//#endregion param
/** /**
* UI,,API.
* see `UpdateTemplateTree`
*
*
*
* ### (,)
*
* - ()()
* ,,.
*
* - [](mobx),`positioning`.
* `positioning`. `LWH`,`XYZ`.
*
* - ()使,,便.
* 使,.
*
* - ():
* .{RX RY RZ}
* ,使,~.()
*
* ###
*
* - `LWH``positioning`,.
*
* - (),().
* *
*/ */
async UpdateTemplate(params?: {}, recursion = false) private async Update()
{ {
if (!params) let vardefines = this.GetParameterDefinition(false);
params = this.GetParentParams(); let brs = this.Objects.filter(id => !id.IsErase).map(id => id.Object as Board);
else let evaled = new Set<TemplateParam>();
{
let newParams = {}; let spaceCS = this.GetTemplateSpaceCS(false);
for (let key in params) let spaceSize: Vector3;
{
if (key[0] !== "@") let paramMap = new Map<string, TemplateParam>();
newParams["_" + key] = params[key]; for (let param of this.Params)
else paramMap.set(param.name, param);
newParams[key] = params[key];
} for (let br of brs)
params = newParams; br.ApplyMatrix(br.SpaceOCSInv);
} //#region 1.定位(坐标系和大小)
let objs = this.Objects.filter(id => !id.IsErase).map(id => id.Object as Board);
if (this.positioning) if (this.positioning)
{ {
await this.positioning.Positioning(); await this.positioning.Positioning();
if (!this.positioning.SpaceCS) if (!this.positioning.SpaceCS)
return;//出事故 return;//出事故
let p = this.positioning.SpaceBox.min.applyMatrix4(this.positioning.SpaceCS); spaceCS = this.positioning.SpaceCS;
this.positioning.SpaceCS.setPosition(p); spaceSize = this.positioning.SpaceSize;
for (let ent of objs)
{
// let m = ent.SpaceOCSInv.multiply(this.positioning.SpaceCS);
ent.ApplyMatrix(ent.SpaceOCSInv);
ent.ApplyMatrix(this.positioning.SpaceCS);
}
if (this.positioning.SpaceSize) spaceCS = this.RotateSpaceCS(vardefines, evaled, spaceCS, spaceSize);
{ //更新LWH(通过定位空间)
this.LParam.UpdateParam(this.positioning.SpaceSize.x); this.LParam.UpdateParam(spaceSize.x);
this.WParam.UpdateParam(this.positioning.SpaceSize.y); this.WParam.UpdateParam(spaceSize.y);
this.HParam.UpdateParam(this.positioning.SpaceSize.z); this.HParam.UpdateParam(spaceSize.z);
} }
else
{
//保持SpaceCS this.LParam.EvalUpdate(vardefines, paramMap, evaled);
for (let ent of objs) this.WParam.EvalUpdate(vardefines, paramMap, evaled);
this.HParam.EvalUpdate(vardefines, paramMap, evaled);
this.PXParam.EvalUpdate(vardefines, paramMap, evaled);
this.PYParam.EvalUpdate(vardefines, paramMap, evaled);
this.PZParam.EvalUpdate(vardefines, paramMap, evaled);
let l = this.LParam.value as number;
let w = this.WParam.value as number;
let h = this.HParam.value as number;
spaceSize = new Vector3(l, w, h);
//相对定位. use PX PY pZ
let baseP = new Vector3(this.PXParam.value as number, this.PYParam.value as number, this.PZParam.value as number);
baseP.applyMatrix4(spaceCS);
spaceCS.setPosition(baseP);
if (!this.Parent)
{ {
ent.SpaceOCS = this.positioning.SpaceCS; this.PXParam.value = 0;
this.PXParam.expr = "";
this.PYParam.value = 0;
this.PYParam.expr = "";
this.PZParam.value = 0;
this.PZParam.expr = "";
} }
spaceCS = this.RotateSpaceCS(vardefines, evaled, spaceCS, spaceSize);
//更新LWH(通过定位空间)
this.LParam.UpdateParam(spaceSize.x);
this.WParam.UpdateParam(spaceSize.y);
this.HParam.UpdateParam(spaceSize.z);
}
vardefines["L"] = spaceSize.x;
vardefines["W"] = spaceSize.y;
vardefines["H"] = spaceSize.z;
//#endregion
//#region 3.应用更新到定位空间
//变换到新的模版空间
for (let br of brs)
br.ApplyMatrix(spaceCS);
//#endregion
//更新其他参数变量 Eval local params
for (const param of this.Params)
{
param.EvalUpdate(vardefines, paramMap, evaled);
}
//保持SpaceCS
for (let ent of brs)
{
ent.SpaceOCS = spaceCS;
}
//Cache
this._CacheParamVars = vardefines;
this._CacheSpaceCS = spaceCS;
}
/**
* ,,SpaceSizeSpaceCS
*/
private RotateSpaceCS(vardefines: any, evaled: Set<TemplateParam>, spaceCS: Matrix4, spaceSize: Vector3)
{
this.RXParam.EvalUpdate(vardefines, this.Params, evaled);
this.RYParam.EvalUpdate(vardefines, this.Params, evaled);
this.RZParam.EvalUpdate(vardefines, this.Params, evaled);
//use RX RY RZ
let rx = Math.degToRad(this.RXParam.value as number);
let ry = Math.degToRad(this.RYParam.value as number);
let rz = Math.degToRad(this.RZParam.value as number);
if (rx !== 0 || ry !== 0 || rz !== 0)
{
let mrx = new Matrix4().makeRotationX(rx);
let mry = new Matrix4().makeRotationY(ry);
let mrz = new Matrix4().makeRotationZ(rz);
let mro = mrz.multiply(mry.multiply(mrx));
let roSpace = mro.multiply(spaceCS);
let roSpaceInv = mrx.getInverse(roSpace); //变量复用
let transfromToRoSpace = roSpaceInv.multiply(spaceCS);
let box = new Box3(new Vector3(), spaceSize.clone());
box.applyMatrix4(transfromToRoSpace);
box.getSize(spaceSize);
let baseP = box.min.clone().applyMatrix4(roSpace);
roSpace.setPosition(baseP);
//更新LWH(通过定位空间)
this.LParam.UpdateParam(spaceSize.x);
this.WParam.UpdateParam(spaceSize.y);
this.HParam.UpdateParam(spaceSize.z);
spaceCS = roSpace;
} }
return spaceCS;
}
if (recursion) /** 以广度搜索优先更新节点树 */
async UpdateTemplateTree()
{
let stack: TemplateRecord[] = [this];
await this.Update();
while (stack.length > 0)
{ {
//广度优先 let template = stack.pop();
let updateStack = [...this.Children];
let childrenCount = this.Children.length; //计算DIV(给子空间使用)
let index = 0; if (template.Children.length > 0 && template.SplitType !== TemplateSplitType.None)
while (updateStack.length > 0)
{ {
if (index < childrenCount) let vardefines = (<TemplateRecord>template.Children[0].Object).GetParameterDefinition();
vardefines._DIV = 0;
let sum = 0;
for (let c of template.Children)
{ {
params["index"] = index; let ctemplate = c.Object as TemplateRecord;
params["childrenCount"] = childrenCount; let param = ctemplate.Params[template.SplitType];
sum += param.EvalUpdate(vardefines, [], new Set(), false);
} }
else
let sumDiv = 0;
vardefines._DIV = 1;
for (let c of template.Children)
{ {
delete params["index"]; let ctemplate = c.Object as TemplateRecord;
delete params["childrenCount"]; let param = ctemplate.Params[template.SplitType];
sum += param.EvalUpdate(vardefines, [], new Set(), false);
} }
let id = updateStack.shift(); let divCount = sum - sumDiv;
let template = id.Object as TemplateRecord;
await template.UpdateTemplate(params); if (divCount > 0)
updateStack.push(...template.Children); template._CacheParamVars.DIV = (template.Params[template.SplitType].value as number - sum) / divCount;
template._CacheParamVars.POS = 0;
}
for (let c of template.Children)
{
let ctemplate = c.Object as TemplateRecord;
stack.push(ctemplate);
await ctemplate.Update();
index++; if (template._CacheParamVars.DIV !== undefined)//更新POS
template._CacheParamVars.POS += ctemplate.Params[template.SplitType].value as number;
} }
} }
} }
private GetParentParams() /** 缓存本节点的变量定义值,当子层需要本层的参数时,可以直接获取 */
private _CacheParamVars: any;
private _CacheSpaceCS: Matrix4;
/**
* .()
* @param [useCache=true] ,使,()
* @returns
*/
private GetParameterDefinition(useCache = true): any
{ {
let params = {}; if (this._CacheParamVars && useCache)
let parent = this.Parent; return this._CacheParamVars;
let index = 1;
while (parent) let vars = this.GetParentParams();
for (const param of this.Params)
{ {
let parentTemplate = parent.Object as TemplateRecord; vars[param.name] = param.value;
let frontStr = new Array(index).fill("_").join(); if (!this.Parent)
for (let param of parentTemplate.Params) vars["$" + param.name] = param.value;//root
params[frontStr + param.name] = param.value; }
if (index === 1)
{ this._CacheParamVars = vars;
let recordIndex = parentTemplate.Children.indexOf(this.Id); return vars;
} }
parent = parentTemplate.Parent;
if (!parent) /**
*
* - ,`_`
* - `$`
*
* @returns
*/
private GetParentParams(): Object
{
if (!this.Parent) return {};
let parent = this.Parent.Object as TemplateRecord;
let params = parent.GetParameterDefinition();
let newParams = {};
for (let key in params)
{
if (key[0] !== "$")
newParams["_" + key] = params[key];
else
newParams[key] = params[key];
}
params = newParams;
return params;
}
/**
*
* - 使
* - 使
*
* -
*
* @param [useCache=true] ,使,()
*/
private GetTemplateSpaceCS(useCache = true): Matrix4
{
if (useCache && this._CacheSpaceCS)
return this._CacheSpaceCS.clone();
if (this.Parent)
{
let template = this.Parent.Object as TemplateRecord;
return template.GetTemplateSpaceCS();
}
for (let brId of this.Objects)
{
if (brId.Object && !brId.IsErase)
{ {
for (let param of parentTemplate.Params) let br = brId.Object as Board;
params["@" + param.name] = param.value; return br.SpaceOCS;
} }
index++;
} }
return params;
return new Matrix4();
} }
//#region -------------------------File------------------------- //#region -------------------------File-------------------------
@ -307,11 +513,14 @@ export class TemplateRecord extends SymbolTableRecord
this.Objects.push(file.ReadObjectId()); this.Objects.push(file.ReadObjectId());
this.positioning = file.ReadObject(); this.positioning = file.ReadObject();
if (ver > 1)
this.SplitType = file.Read();
} }
//对象将自身数据写入到文件. //对象将自身数据写入到文件.
WriteFile(file: CADFiler) WriteFile(file: CADFiler)
{ {
file.Write(1); file.Write(2);
super.WriteFile(file); super.WriteFile(file);
file.Write(this.Type); file.Write(this.Type);
file.WriteObjectId(this.Parent); file.WriteObjectId(this.Parent);
@ -326,6 +535,8 @@ export class TemplateRecord extends SymbolTableRecord
file.WriteObjectId(id); file.WriteObjectId(id);
file.WriteObject(this.positioning); file.WriteObject(this.positioning);
file.Write(this.SplitType);
} }
//#endregion //#endregion
} }

@ -15,39 +15,22 @@ import { TemplateStretchScaleBoxAction } from "./Action/TemplateStretchScaleBoxA
import { TemplateRecord } from "./TemplateRecord"; import { TemplateRecord } from "./TemplateRecord";
import { ClampSpaceParse } from "../../Geometry/SpaceParse/ClampSpaceParse"; import { ClampSpaceParse } from "../../Geometry/SpaceParse/ClampSpaceParse";
import { PositioningClampSpace } from "./Positioning/PositioningClampSpace"; import { PositioningClampSpace } from "./Positioning/PositioningClampSpace";
import { Sleep } from "../../Common/Sleep";
/** import { TemplateSplitType } from "./TemplateType";
* import { TemplateParam } from "./Param/TemplateParam";
*/ import { TemplateParamType } from "./Param/TemplateParamType";
function ParamRegister(params: {}, name: string, value: string, isRoot = false) import { FilletUtils } from "../../Add-on/FilletUtils";
{ import { Polyline } from "../Entity/Polyline";
params[name] = value; import { Line } from "../Entity/Line";
if (isRoot) import { IntersectOption } from "../../GraphicsSystem/IntersectWith";
params["@" + name] = value; import { TemplateFilletAction } from "./Action/TemplateFilletAction";
}
/**
*
*/
function ParameterBecomeFater(params: {})
{
let nparams = {};
for (let name in params)
{
if (name[0] === "@")
nparams[name] = params[name];
else
nparams["_" + name] = params[name];
}
return nparams;
}
export function GetDefaultTemplate() export function GetDefaultTemplate()
{ {
let templates = app.Database.TemplateTable.Objects; let templates = app.Database.TemplateTable.Objects;
if (templates.length === 0) if (templates.length === 0)
{ {
let template = new TemplateRecord().InitSizeParams(); let template = new TemplateRecord().InitBaseParams();
app.Database.TemplateTable.Append(template); app.Database.TemplateTable.Append(template);
return template; return template;
} }
@ -178,6 +161,7 @@ export class AutoTempateSizeAction
//归0? //归0?
let keyRes = await app.Editor.GetKeyWords({ let keyRes = await app.Editor.GetKeyWords({
Msg: "自动将所有的板件移动到0点后初始化动作?",
KeyWordList: [ KeyWordList: [
{ key: "Y", msg: "是" }, { key: "Y", msg: "是" },
{ key: "N", msg: "否" }, { key: "N", msg: "否" },
@ -214,7 +198,14 @@ export class AutoTempateSizeAction
//上缩 //上缩
let topBox = new Box3(box.min.clone().add(new Vector3(-1, -1, size.z / 2)), box.max.clone().add(v)); let topBox = new Box3(box.min.clone().add(new Vector3(-1, -1, size.z / 2)), box.max.clone().add(v));
let template = new TemplateRecord().InitSizeParams(); let template = new TemplateRecord().InitBaseParams();
let rParam = new TemplateParam();
rParam.name = "R";
rParam.value = 0;
rParam.type = TemplateParamType.Float;
template.Params.push(rParam);
app.Database.TemplateTable.Append(template); app.Database.TemplateTable.Append(template);
template.GetParam("L").value = size.x; template.GetParam("L").value = size.x;
template.GetParam("W").value = size.y; template.GetParam("W").value = size.y;
@ -343,8 +334,8 @@ export class UpdateTemplate
if (newV.Status === PromptStatus.OK) if (newV.Status === PromptStatus.OK)
{ {
param.UpdateParam(newV.Distance); param.expr = newV.Distance;
template.UpdateTemplate(undefined, true); await template.UpdateTemplateTree();
} }
} }
else else
@ -353,6 +344,41 @@ export class UpdateTemplate
} }
} }
class UpdateTemplateRo
{
async exec()
{
let enRes = await app.Editor.GetSelection({
Msg: "选择要修改的模版:",
Once: true,
Filter: {
filterFunction: (obj, ent) =>
{
return ent.Template !== undefined;
}
}
});
if (enRes.Status !== PromptStatus.OK) return;
let template = enRes.SelectSet.SelectEntityList[0].Template.Object as TemplateRecord;
let ros = [0, 90, 180, 270, 0];
for (let param of [template.RXParam, template.RYParam, template.RZParam])
{
for (let r of ros)
{
param.expr = r;
await template.UpdateTemplateTree();
app.Editor.UpdateScreen();
await Sleep(1000);
}
}
}
}
export class UpdateParam2 export class UpdateParam2
{ {
timer; timer;
@ -395,7 +421,7 @@ export class UpdateParam2
param.UpdateParam(param.value as number - 150); param.UpdateParam(param.value as number - 150);
} }
template.UpdateTemplate(undefined, true); template.UpdateTemplateTree();
app.Editor.UpdateScreen(); app.Editor.UpdateScreen();
index++; index++;
}, 16) }, 16)
@ -447,7 +473,7 @@ export class TemplateAttach
let positioning = new PositioningClampSpace(); let positioning = new PositioningClampSpace();
positioning.FromSpaceParse(parse); positioning.FromSpaceParse(parse);
template.Positioning = positioning; template.Positioning = positioning;
await template.UpdateTemplate();//单独更新 不继承 await template.UpdateTemplateTree();//单独更新 不继承
let tbrs = brs.filter(br => br.Template !== undefined); let tbrs = brs.filter(br => br.Template !== undefined);
if (tbrs.length === 0) if (tbrs.length === 0)
@ -471,13 +497,172 @@ export class TemplateAttach
} }
} }
export class TemplateAttach2
{
async exec()
{
let enRes = await app.Editor.GetEntity({
Msg: "选择附加的模版",
NotNone: true,
Filter: {
filterFunction: (obj, ent) =>
{
return ent.Template !== undefined;
}
}
});
if (enRes.Status !== PromptStatus.OK) return;
let e = enRes.Entity;
let template = e.Template.Object as TemplateRecord;
let selectSpace = new PointSelectSpaceClamp();
selectSpace.Enable = EnableSelectType.Stretch;
await selectSpace.Select();
if (!selectSpace.ParseOK)
{
app.Editor.Prompt("未能分析出有效空间!");
return;
}
let parse = selectSpace.SpaceParse as ClampSpaceParse;
let brs = parse.m_Boards;
let positioning = new PositioningClampSpace();
positioning.FromSpaceParse(parse);
let tbrs = brs.filter(br => br.Template !== undefined);
if (tbrs.length === 0)
{
app.Editor.Prompt("选取的空间不存在模版!");
}
else
{
tbrs.sort((b1, b2) =>
{
let t1 = b1.Template.Object as TemplateRecord;
let t2 = b2.Template.Object as TemplateRecord;
return t2.NodeDepth - t1.NodeDepth;
});
let templateSpace = new TemplateRecord().InitBaseParams();
templateSpace.SplitType = TemplateSplitType.Z;
templateSpace.Positioning = positioning;
app.Database.TemplateTable.Append(templateSpace);
let template1 = new TemplateRecord().InitBaseParams();
template1.LParam.expr = "_L";
template1.WParam.expr = "_W";
template1.HParam.expr = "_DIV";
template1.PZParam.expr = "_POS";
let template2 = template1.Clone();
app.Database.TemplateTable.Append(template1);
app.Database.TemplateTable.Append(template2);
template.LParam.expr = "_L";
template.WParam.expr = "_W";
template.HParam.expr = "_DIV";
template.PZParam.expr = "_POS";
templateSpace.Children.push(template1.Id);
templateSpace.Children.push(template.Id);
templateSpace.Children.push(template2.Id);
let templateSource = tbrs[0].Template.Object as TemplateRecord;
templateSource.Children.push(templateSpace.Id);
await templateSpace.UpdateTemplateTree();
}
}
}
export class TemplateAddFilletAction
{
async exec()
{
let brRes = await app.Editor.GetEntity({
Msg: "选择附加的模版",
NotNone: true,
Filter: {
filterFunction: (obj, ent) =>
{
if (ent instanceof Board)
return ent.Template !== undefined;
return false;
}
}
});
if (brRes.Status !== PromptStatus.OK) return;
//------1.画辅助线
let ptRes = await app.Editor.GetPoint({
BasePoint: brRes.Point,
AllowDrawRubberBand: true,
AllowNone: true,
Msg: "选择下一个点:"
});
if (ptRes.Status === PromptStatus.Cancel)
return;
//------2.倒角
let fillet = new FilletUtils();
fillet.FilletRadius = 100;
let fres = fillet.FilletBoard(brRes, ptRes);
if (fres instanceof Polyline)
{
let br = brRes.Entity as Board;
br.ContourCurve = fres;
let brContour = fres;
//------1.求交
let brResPt = brRes.Point.clone().applyMatrix4(br.OCSInv).setZ(0);
let ptResPt = ptRes.Point.clone().applyMatrix4(br.OCSInv).setZ(0);
let l = new Line(brResPt, ptResPt);
let ipts = l.IntersectWith(brContour, IntersectOption.ExtendThis);
if (ipts.length > 2)//超过2个则有可能有多余交点
//找最近点
ipts = [fillet.FindNearestPt(ipts, brResPt), fillet.FindNearestPt(ipts, ptResPt)]
if (ipts.length !== 2)
return "倒角失败!交点个数异常.";
let param1 = brContour.GetParamAtPoint(ipts[0]);
let param2 = brContour.GetParamAtPoint(ipts[1]);
let filletAction = new TemplateFilletAction(br.Id, param1, param2);
let template = br.Template.Object as TemplateRecord;
let rParam = template.GetParam("R");
rParam.actions.push(filletAction);
}
else
app.Editor.Prompt(fres);
}
}
commandMachine.RegisterCommand("Attach", new TemplateAttach()); commandMachine.RegisterCommand("Attach", new TemplateAttach());
commandMachine.RegisterCommand("Attach2", new TemplateAttach2());
commandMachine.RegisterCommand("templateAddFilletAction", new TemplateAddFilletAction());
commandMachine.RegisterCommand("al", new AddTemplateAction("L")); commandMachine.RegisterCommand("al", new AddTemplateAction("L"));
commandMachine.RegisterCommand("aw", new AddTemplateAction("W")); commandMachine.RegisterCommand("aw", new AddTemplateAction("W"));
commandMachine.RegisterCommand("ah", new AddTemplateAction("H")); commandMachine.RegisterCommand("ah", new AddTemplateAction("H"));
commandMachine.RegisterCommand("uu", new UpdateTemplate()); commandMachine.RegisterCommand("uu", new UpdateTemplate());
commandMachine.RegisterCommand("uur", new UpdateTemplateRo());
commandMachine.RegisterCommand("uuu", new UpdateParam2()); commandMachine.RegisterCommand("uuu", new UpdateParam2());
commandMachine.RegisterCommand("clear", new Clear); commandMachine.RegisterCommand("clear", new Clear);

@ -11,3 +11,11 @@ export enum TemplateType
//阵列模版 //阵列模版
Array Array
} }
export enum TemplateSplitType
{
None = -1,
X = 0,
Y = 1,
Z = 2,
}

Loading…
Cancel
Save