Add boundary constraint behavior

This commit is contained in:
MrKBear 2022-03-30 19:14:24 +08:00
parent 17ee906f90
commit 8e413f0d1c
6 changed files with 120 additions and 24 deletions

View File

@ -2,10 +2,12 @@ import { BehaviorRecorder, IAnyBehaviorRecorder } from "@Model/Behavior";
import { Template } from "./Template";
import { Dynamics } from "./Dynamics";
import { Brownian } from "./Brownian";
import { BoundaryConstraint } from "./BoundaryConstraint";
const AllBehaviors: IAnyBehaviorRecorder[] = [
new BehaviorRecorder(Dynamics),
new BehaviorRecorder(Brownian)
new BehaviorRecorder(Brownian),
new BehaviorRecorder(BoundaryConstraint)
]
/**
@ -51,6 +53,4 @@ function categoryBehaviors(behaviors: IAnyBehaviorRecorder[]): ICategory[] {
return res;
}
console.log(AllBehaviorsWithCategory)
export { AllBehaviors, AllBehaviorsWithCategory, ICategory as ICategoryBehavior };

View 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 };

View File

@ -42,7 +42,7 @@ class Brownian extends Behavior<IBrownianBehaviorParameter, IBrownianBehaviorEve
maxStrength: {
type: "number",
name: "$Max.Strength",
defaultValue: .1,
defaultValue: 10,
numberStep: .01,
numberMin: 0
},

View File

@ -35,22 +35,22 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve
maxAcceleration: {
name: "$Max.Acceleration",
type: "number",
defaultValue: 0.5,
numberStep: .01,
defaultValue: 5,
numberStep: .1,
numberMin: 0
},
maxVelocity: {
name: "$Max.Velocity",
type: "number",
defaultValue: 0.5,
numberStep: .01,
defaultValue: 10,
numberStep: .1,
numberMin: 0
},
resistance: {
name: "$Resistance",
type: "number",
defaultValue: .01,
numberStep: .001,
defaultValue: 0.1,
numberStep: .1,
numberMin: 0
}
};
@ -88,18 +88,29 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve
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[1] = individual.force[1] * resistance / this.parameter.mass;
individual.acceleration[2] = individual.force[2] * resistance / this.parameter.mass;
individual.acceleration[0] = individual.force[0] / this.parameter.mass;
individual.acceleration[1] = individual.force[1] / this.parameter.mass;
individual.acceleration[2] = individual.force[2] / this.parameter.mass;
// 加速度约束
const overA = Math.max(individual.vectorLength(individual.acceleration) - this.parameter.maxAcceleration, 0);
individual.acceleration[0] = individual.acceleration[0] - individual.acceleration[0] * overA;
individual.acceleration[1] = individual.acceleration[1] - individual.acceleration[1] * overA;
individual.acceleration[2] = individual.acceleration[2] - individual.acceleration[2] * overA;
const lengthA = individual.vectorLength(individual.acceleration);
if (lengthA > this.parameter.maxAcceleration) {
individual.acceleration[0] = individual.acceleration[0] * this.parameter.maxAcceleration / lengthA;
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;
@ -107,15 +118,22 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve
individual.velocity[2] = individual.velocity[2] + individual.acceleration[2] * t;
// 速度约束
const overV = Math.max(individual.vectorLength(individual.velocity) - this.parameter.maxVelocity, 0);
individual.velocity[0] = individual.velocity[0] - individual.velocity[0] * overV;
individual.velocity[1] = individual.velocity[1] - individual.velocity[1] * overV;
individual.velocity[2] = individual.velocity[2] - individual.velocity[2] * overV;
const lengthV = individual.vectorLength(individual.velocity);
if (lengthV > this.parameter.maxVelocity) {
individual.velocity[0] = individual.velocity[0] * this.parameter.maxVelocity / lengthV;
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[1] = individual.position[1] + individual.velocity[1] * t;
individual.position[2] = individual.position[2] + individual.velocity[2] * t;
// 清除受力
individual.force[0] = 0;
individual.force[1] = 0;
individual.force[2] = 0;
};
}

View File

@ -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;
public tickerType: 1 | 2 = 1;
public tickerType: 1 | 2 = 2;
private ticker(t: number) {
if (this.startFlag && t !== 0) {

View File

@ -59,8 +59,12 @@ class SimulatorWeb extends Component {
dynamic.name = "dynamic";
let brownian = this.status.model.addBehavior(AllBehaviors[1]);
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(brownian);
group.addBehavior(boundary);
}
(window as any).s = this;