Add boundary constraint behavior
This commit is contained in:
parent
17ee906f90
commit
8e413f0d1c
@ -2,10 +2,12 @@ import { BehaviorRecorder, IAnyBehaviorRecorder } from "@Model/Behavior";
|
|||||||
import { Template } from "./Template";
|
import { Template } from "./Template";
|
||||||
import { Dynamics } from "./Dynamics";
|
import { Dynamics } from "./Dynamics";
|
||||||
import { Brownian } from "./Brownian";
|
import { Brownian } from "./Brownian";
|
||||||
|
import { BoundaryConstraint } from "./BoundaryConstraint";
|
||||||
|
|
||||||
const AllBehaviors: IAnyBehaviorRecorder[] = [
|
const AllBehaviors: IAnyBehaviorRecorder[] = [
|
||||||
new BehaviorRecorder(Dynamics),
|
new BehaviorRecorder(Dynamics),
|
||||||
new BehaviorRecorder(Brownian)
|
new BehaviorRecorder(Brownian),
|
||||||
|
new BehaviorRecorder(BoundaryConstraint)
|
||||||
]
|
]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,6 +53,4 @@ function categoryBehaviors(behaviors: IAnyBehaviorRecorder[]): ICategory[] {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(AllBehaviorsWithCategory)
|
|
||||||
|
|
||||||
export { AllBehaviors, AllBehaviorsWithCategory, ICategory as ICategoryBehavior };
|
export { AllBehaviors, AllBehaviorsWithCategory, ICategory as ICategoryBehavior };
|
74
source/Behavior/BoundaryConstraint.ts
Normal file
74
source/Behavior/BoundaryConstraint.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import { Behavior } from "@Model/Behavior";
|
||||||
|
import { Group } from "@Model/Group";
|
||||||
|
import { Individual } from "@Model/Individual";
|
||||||
|
import { Label } from "@Model/Label";
|
||||||
|
import { Model } from "@Model/Model";
|
||||||
|
import { Range } from "@Model/Range";
|
||||||
|
|
||||||
|
type IBoundaryConstraintBehaviorParameter = {
|
||||||
|
range: "LR"
|
||||||
|
}
|
||||||
|
|
||||||
|
type IBoundaryConstraintBehaviorEvent = {}
|
||||||
|
|
||||||
|
class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter, IBoundaryConstraintBehaviorEvent> {
|
||||||
|
|
||||||
|
public override behaviorId: string = "BoundaryConstraint";
|
||||||
|
|
||||||
|
public override behaviorName: string = "$Title";
|
||||||
|
|
||||||
|
public override iconName: string = "Running";
|
||||||
|
|
||||||
|
public override describe: string = "$Intro";
|
||||||
|
|
||||||
|
public override category: string = "$Physics";
|
||||||
|
|
||||||
|
public override parameterOption = {
|
||||||
|
range: {
|
||||||
|
type: "LR",
|
||||||
|
name: "$range",
|
||||||
|
defaultValue: undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public override terms: Record<string, Record<string, string>> = {
|
||||||
|
"$Title": {
|
||||||
|
"ZH_CN": "边界约束",
|
||||||
|
"EN_US": "Boundary constraint"
|
||||||
|
},
|
||||||
|
"$Intro": {
|
||||||
|
"ZH_CN": "个体越出边界后将主动返回",
|
||||||
|
"EN_US": "Individuals will return actively after crossing the border"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public effect(individual: Individual, group: Group, model: Model, t: number): void {
|
||||||
|
let rangeList: Range[] = [];
|
||||||
|
if (this.parameter.range instanceof Range) {
|
||||||
|
rangeList.push(this.parameter.range);
|
||||||
|
}
|
||||||
|
if (this.parameter.range instanceof Label) {
|
||||||
|
rangeList = model.getObjectByLabel(this.parameter.range).filter((obj) => {
|
||||||
|
return obj instanceof Range
|
||||||
|
}) as any;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < rangeList.length; i++) {
|
||||||
|
|
||||||
|
let rx = rangeList[i].position[0] - individual.position[0];
|
||||||
|
let ry = rangeList[i].position[1] - individual.position[1];
|
||||||
|
let rz = rangeList[i].position[2] - individual.position[2];
|
||||||
|
|
||||||
|
let ox = Math.abs(rx) > rangeList[i].radius[0];
|
||||||
|
let oy = Math.abs(ry) > rangeList[i].radius[1];
|
||||||
|
let oz = Math.abs(rz) > rangeList[i].radius[2];
|
||||||
|
|
||||||
|
individual.applyForce(
|
||||||
|
ox ? rx : 0,
|
||||||
|
oy ? ry : 0,
|
||||||
|
oz ? rz : 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { BoundaryConstraint };
|
@ -42,7 +42,7 @@ class Brownian extends Behavior<IBrownianBehaviorParameter, IBrownianBehaviorEve
|
|||||||
maxStrength: {
|
maxStrength: {
|
||||||
type: "number",
|
type: "number",
|
||||||
name: "$Max.Strength",
|
name: "$Max.Strength",
|
||||||
defaultValue: .1,
|
defaultValue: 10,
|
||||||
numberStep: .01,
|
numberStep: .01,
|
||||||
numberMin: 0
|
numberMin: 0
|
||||||
},
|
},
|
||||||
|
@ -35,22 +35,22 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve
|
|||||||
maxAcceleration: {
|
maxAcceleration: {
|
||||||
name: "$Max.Acceleration",
|
name: "$Max.Acceleration",
|
||||||
type: "number",
|
type: "number",
|
||||||
defaultValue: 0.5,
|
defaultValue: 5,
|
||||||
numberStep: .01,
|
numberStep: .1,
|
||||||
numberMin: 0
|
numberMin: 0
|
||||||
},
|
},
|
||||||
maxVelocity: {
|
maxVelocity: {
|
||||||
name: "$Max.Velocity",
|
name: "$Max.Velocity",
|
||||||
type: "number",
|
type: "number",
|
||||||
defaultValue: 0.5,
|
defaultValue: 10,
|
||||||
numberStep: .01,
|
numberStep: .1,
|
||||||
numberMin: 0
|
numberMin: 0
|
||||||
},
|
},
|
||||||
resistance: {
|
resistance: {
|
||||||
name: "$Resistance",
|
name: "$Resistance",
|
||||||
type: "number",
|
type: "number",
|
||||||
defaultValue: .01,
|
defaultValue: 0.1,
|
||||||
numberStep: .001,
|
numberStep: .1,
|
||||||
numberMin: 0
|
numberMin: 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -88,18 +88,29 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve
|
|||||||
const currentV = individual.vectorLength(individual.velocity);
|
const currentV = individual.vectorLength(individual.velocity);
|
||||||
|
|
||||||
// 计算阻力
|
// 计算阻力
|
||||||
const resistance = Math.max(1 - currentV * currentV * this.parameter.resistance, 0);
|
const resistance = currentV * currentV * this.parameter.resistance;
|
||||||
|
|
||||||
|
// 应用阻力
|
||||||
|
if (currentV) {
|
||||||
|
individual.applyForce(
|
||||||
|
(- individual.velocity[0] / currentV) * resistance,
|
||||||
|
(- individual.velocity[1] / currentV) * resistance,
|
||||||
|
(- individual.velocity[2] / currentV) * resistance
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 计算加速度
|
// 计算加速度
|
||||||
individual.acceleration[0] = individual.force[0] * resistance / this.parameter.mass;
|
individual.acceleration[0] = individual.force[0] / this.parameter.mass;
|
||||||
individual.acceleration[1] = individual.force[1] * resistance / this.parameter.mass;
|
individual.acceleration[1] = individual.force[1] / this.parameter.mass;
|
||||||
individual.acceleration[2] = individual.force[2] * resistance / this.parameter.mass;
|
individual.acceleration[2] = individual.force[2] / this.parameter.mass;
|
||||||
|
|
||||||
// 加速度约束
|
// 加速度约束
|
||||||
const overA = Math.max(individual.vectorLength(individual.acceleration) - this.parameter.maxAcceleration, 0);
|
const lengthA = individual.vectorLength(individual.acceleration);
|
||||||
individual.acceleration[0] = individual.acceleration[0] - individual.acceleration[0] * overA;
|
if (lengthA > this.parameter.maxAcceleration) {
|
||||||
individual.acceleration[1] = individual.acceleration[1] - individual.acceleration[1] * overA;
|
individual.acceleration[0] = individual.acceleration[0] * this.parameter.maxAcceleration / lengthA;
|
||||||
individual.acceleration[2] = individual.acceleration[2] - individual.acceleration[2] * overA;
|
individual.acceleration[1] = individual.acceleration[1] * this.parameter.maxAcceleration / lengthA;
|
||||||
|
individual.acceleration[2] = individual.acceleration[2] * this.parameter.maxAcceleration / lengthA;
|
||||||
|
}
|
||||||
|
|
||||||
// 计算速度
|
// 计算速度
|
||||||
individual.velocity[0] = individual.velocity[0] + individual.acceleration[0] * t;
|
individual.velocity[0] = individual.velocity[0] + individual.acceleration[0] * t;
|
||||||
@ -107,15 +118,22 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve
|
|||||||
individual.velocity[2] = individual.velocity[2] + individual.acceleration[2] * t;
|
individual.velocity[2] = individual.velocity[2] + individual.acceleration[2] * t;
|
||||||
|
|
||||||
// 速度约束
|
// 速度约束
|
||||||
const overV = Math.max(individual.vectorLength(individual.velocity) - this.parameter.maxVelocity, 0);
|
const lengthV = individual.vectorLength(individual.velocity);
|
||||||
individual.velocity[0] = individual.velocity[0] - individual.velocity[0] * overV;
|
if (lengthV > this.parameter.maxVelocity) {
|
||||||
individual.velocity[1] = individual.velocity[1] - individual.velocity[1] * overV;
|
individual.velocity[0] = individual.velocity[0] * this.parameter.maxVelocity / lengthV;
|
||||||
individual.velocity[2] = individual.velocity[2] - individual.velocity[2] * overV;
|
individual.velocity[1] = individual.velocity[1] * this.parameter.maxVelocity / lengthV;
|
||||||
|
individual.velocity[2] = individual.velocity[2] * this.parameter.maxVelocity / lengthV;
|
||||||
|
}
|
||||||
|
|
||||||
// 应用速度
|
// 应用速度
|
||||||
individual.position[0] = individual.position[0] + individual.velocity[0] * t;
|
individual.position[0] = individual.position[0] + individual.velocity[0] * t;
|
||||||
individual.position[1] = individual.position[1] + individual.velocity[1] * t;
|
individual.position[1] = individual.position[1] + individual.velocity[1] * t;
|
||||||
individual.position[2] = individual.position[2] + individual.velocity[2] * t;
|
individual.position[2] = individual.position[2] + individual.velocity[2] * t;
|
||||||
|
|
||||||
|
// 清除受力
|
||||||
|
individual.force[0] = 0;
|
||||||
|
individual.force[1] = 0;
|
||||||
|
individual.force[2] = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class Actuator extends Emitter<IActuatorEvent> {
|
|||||||
/**
|
/**
|
||||||
* 模拟帧率
|
* 模拟帧率
|
||||||
*/
|
*/
|
||||||
public fps: number = 24;
|
public fps: number = 36;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仿真是否进行
|
* 仿真是否进行
|
||||||
@ -56,7 +56,7 @@ class Actuator extends Emitter<IActuatorEvent> {
|
|||||||
*/
|
*/
|
||||||
private alignTimer: number = 0;
|
private alignTimer: number = 0;
|
||||||
|
|
||||||
public tickerType: 1 | 2 = 1;
|
public tickerType: 1 | 2 = 2;
|
||||||
|
|
||||||
private ticker(t: number) {
|
private ticker(t: number) {
|
||||||
if (this.startFlag && t !== 0) {
|
if (this.startFlag && t !== 0) {
|
||||||
|
@ -59,8 +59,12 @@ class SimulatorWeb extends Component {
|
|||||||
dynamic.name = "dynamic";
|
dynamic.name = "dynamic";
|
||||||
let brownian = this.status.model.addBehavior(AllBehaviors[1]);
|
let brownian = this.status.model.addBehavior(AllBehaviors[1]);
|
||||||
brownian.name = "brownian";
|
brownian.name = "brownian";
|
||||||
|
let boundary = this.status.model.addBehavior(AllBehaviors[2]);
|
||||||
|
boundary.name = "boundary";
|
||||||
|
boundary.parameter.range = this.status.model.allRangeLabel;
|
||||||
group.addBehavior(dynamic);
|
group.addBehavior(dynamic);
|
||||||
group.addBehavior(brownian);
|
group.addBehavior(brownian);
|
||||||
|
group.addBehavior(boundary);
|
||||||
}
|
}
|
||||||
|
|
||||||
(window as any).s = this;
|
(window as any).s = this;
|
||||||
|
Loading…
Reference in New Issue
Block a user