|
|
@ -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.(当纯数字将被直接计算成value而不保存expr).
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* 由于`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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 旋转空间定位,如果旋转成功,那么SpaceSize和SpaceCS都可能被更新
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|