From c44c10ad4215f4ed79a4b74482d8fd1028bdedfb Mon Sep 17 00:00:00 2001 From: MrKBear Date: Wed, 16 Mar 2022 22:08:57 +0800 Subject: [PATCH] Add individuals gen function --- source/Context/Status.tsx | 21 +++- source/Model/Group.ts | 121 ++++++++++++++++++++- source/Model/Model.ts | 1 + source/Panel/GroupDetails/GroupDetails.tsx | 4 +- 4 files changed, 138 insertions(+), 9 deletions(-) diff --git a/source/Context/Status.tsx b/source/Context/Status.tsx index 13227fc..3e0ce63 100644 --- a/source/Context/Status.tsx +++ b/source/Context/Status.tsx @@ -37,6 +37,7 @@ interface IStatusEvent { rangeAttrChange: void; labelAttrChange: void; groupAttrChange: void; + individualChange: void; } class Status extends Emitter { @@ -74,6 +75,16 @@ class Status extends Emitter { */ public focusLabel?: Label; + private drawtimer?: NodeJS.Timeout; + + private delayDraw = () => { + this.drawtimer ? clearTimeout(this.drawtimer) : null; + this.drawtimer = setTimeout(() => { + this.model.draw(); + this.drawtimer = undefined; + }); + } + public constructor() { super(); @@ -85,11 +96,11 @@ class Status extends Emitter { this.model.on("labelChange", () => this.emit("labelChange")); // 对象变换时执行渲染,更新渲染器数据 - this.on("objectChange", () => { - setTimeout(() => { - this.model.draw(); - }); - }) + this.on("objectChange", this.delayDraw); + this.model.on("individualChange", this.delayDraw); + this.model.on("individualChange", () => { + this.emit("individualChange"); + }); } public bindRenderer(renderer: AbstractRenderer) { diff --git a/source/Model/Group.ts b/source/Model/Group.ts index 0e427f4..1ab400b 100644 --- a/source/Model/Group.ts +++ b/source/Model/Group.ts @@ -1,7 +1,8 @@ import { Individual } from "./Individual"; import { CtrlObject } from "./CtrlObject"; import type { Behavior } from "./Behavior"; -import type { Label } from "./Label"; +import { Label } from "./Label"; +import { Range } from "./Range"; enum GenMod { Point = "p", @@ -36,7 +37,123 @@ class Group extends CtrlObject { /** * 生成个数 */ - public genCount?: number = 0; + public genCount: number = 1; + + /** + * 生成错误信息 + */ + public genErrorMessage?: string; + + /** + * 生成错误信息 + */ + public genErrorMessageShowCount?: string; + + private genInSingelRange(count: number, range: Range) { + for (let i = 0; i < count; i++) { + let individual = new Individual(this); + individual.position[0] = range.position[0] + (Math.random() - .5) * 2 * range.radius[0]; + individual.position[1] = range.position[1] + (Math.random() - .5) * 2 * range.radius[1]; + individual.position[2] = range.position[2] + (Math.random() - .5) * 2 * range.radius[2]; + this.add(individual); + } + } + + private genWithPointMod(): boolean { + for (let i = 0; i < this.genCount; i++) { + let individual = new Individual(this); + individual.position[0] = this.genPoint[0]; + individual.position[1] = this.genPoint[1]; + individual.position[2] = this.genPoint[2]; + this.add(individual); + } + return true; + } + + private genWithRangeMod(): boolean { + let rangeList: Range[] = []; + + // 单一范围对象 + if (this.genRange instanceof Range) { + rangeList = [this.genRange]; + } + + // 多重范围对象 + if (this.genRange instanceof Label) { + let objList: CtrlObject[] = this.model.getObjectByLabel(this.genRange); + rangeList = objList.filter((obj) => obj instanceof Range) as Range[] + } + + // 单一范围生成 + if (rangeList.length === 1) { + this.genInSingelRange(this.genCount, rangeList[0]); + return true; + } + + // 多重范围 + else if (rangeList.length > 1) { + let allVolume: number = 0; + let allGenCount: number = 0; + let genData: number[] = []; + + // 计算体积 + for (let i = 0; i < rangeList.length; i++) { + let volume = + rangeList[i].radius[0] * + rangeList[i].radius[1] * + rangeList[i].radius[2]; + allVolume += volume; + genData.push(volume); + } + + // 按权重分配生成个数 + for (let i = 0; i < genData.length; i++) { + const count = Math.floor((genData[i] / allVolume) * this.genCount) + 1; + allGenCount += count; + genData[i] = count; + } + + // 按照溢出个数删除冗余个数 + let morCount = allGenCount - this.genCount; + let safeCount = 0; + while (morCount > 0 && safeCount < 1000) { + safeCount ++; + let randomIndex = Math.floor(Math.random() * genData.length); + if (genData[randomIndex] > 0) { + genData[randomIndex] --; + morCount --; + } + } + + // 数据生成 + for (let i = 0; i < rangeList.length; i++) { + this.genInSingelRange(genData[i], rangeList[i]); + } + + return true; + } + + return false; + } + + /** + * 生成个体 + */ + public genIndividuals(): boolean { + let success = false; + switch (this.genMethod) { + case GenMod.Point: + success = this.genWithPointMod(); + break; + case GenMod.Range: + success = this.genWithRangeMod(); + break; + } + if (success) { + this.model.emit("individualChange", this); + } + return success; + } /** * 创建个体 diff --git a/source/Model/Model.ts b/source/Model/Model.ts index 24179b6..807dd64 100644 --- a/source/Model/Model.ts +++ b/source/Model/Model.ts @@ -17,6 +17,7 @@ type ModelEvent = { objectAdd: CtrlObject; objectDelete: CtrlObject[]; objectChange: CtrlObject[]; + individualChange: Group; }; /** diff --git a/source/Panel/GroupDetails/GroupDetails.tsx b/source/Panel/GroupDetails/GroupDetails.tsx index c03ce9c..fdc5fe5 100644 --- a/source/Panel/GroupDetails/GroupDetails.tsx +++ b/source/Panel/GroupDetails/GroupDetails.tsx @@ -116,7 +116,7 @@ class GroupDetails extends Component { { this.props.status?.changeGroupAttrib(group.id, "genCount", (val as any) / 1); }} @@ -130,7 +130,7 @@ class GroupDetails extends Component { keyI18n="Common.Attr.Key.Generation" onIconName="BuildDefinition" offIconName="BuildDefinition" valueChange={() => { - console.log("gen"); + group.genIndividuals(); }} />