Add sample tracking behavior
This commit is contained in:
		
							parent
							
								
									571e80d542
								
							
						
					
					
						commit
						4768667803
					
				| @ -12,6 +12,7 @@ import { DirectionCluster } from "@Behavior/DirectionCluster"; | |||||||
| import { CentralCluster } from "@Behavior/CentralCluster"; | import { CentralCluster } from "@Behavior/CentralCluster"; | ||||||
| import { Manufacture } from "@Behavior/Manufacture"; | import { Manufacture } from "@Behavior/Manufacture"; | ||||||
| import { Wastage } from "@Behavior/Wastage"; | import { Wastage } from "@Behavior/Wastage"; | ||||||
|  | import { SampleTracking } from "@Behavior/SampleTracking"; | ||||||
| 
 | 
 | ||||||
| const AllBehaviors: IAnyBehaviorRecorder[] = [ | const AllBehaviors: IAnyBehaviorRecorder[] = [ | ||||||
|     new BehaviorRecorder(Template), |     new BehaviorRecorder(Template), | ||||||
| @ -27,6 +28,7 @@ const AllBehaviors: IAnyBehaviorRecorder[] = [ | |||||||
|     new BehaviorRecorder(CentralCluster), |     new BehaviorRecorder(CentralCluster), | ||||||
|     new BehaviorRecorder(Manufacture), |     new BehaviorRecorder(Manufacture), | ||||||
|     new BehaviorRecorder(Wastage), |     new BehaviorRecorder(Wastage), | ||||||
|  |     new BehaviorRecorder(SampleTracking), | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
							
								
								
									
										154
									
								
								source/Behavior/SampleTracking.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								source/Behavior/SampleTracking.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,154 @@ | |||||||
|  | import { Behavior } from "@Model/Behavior"; | ||||||
|  | import { Group } from "@Model/Group"; | ||||||
|  | import { Individual } from "@Model/Individual"; | ||||||
|  | import { Model } from "@Model/Model"; | ||||||
|  | 
 | ||||||
|  | type ISampleTrackingBehaviorParameter = { | ||||||
|  |     target: "CLG", | ||||||
|  | 	strength: "number", | ||||||
|  |     range: "number", | ||||||
|  |     angle: "number", | ||||||
|  |     accuracy: "number" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ISampleTrackingBehaviorEvent = {} | ||||||
|  | 
 | ||||||
|  | class SampleTracking extends Behavior<ISampleTrackingBehaviorParameter, ISampleTrackingBehaviorEvent> { | ||||||
|  | 
 | ||||||
|  |     public override behaviorId: string = "SampleTracking"; | ||||||
|  | 
 | ||||||
|  |     public override behaviorName: string = "$Title"; | ||||||
|  | 
 | ||||||
|  |     public override iconName: string = "Video360Generic"; | ||||||
|  | 
 | ||||||
|  |     public override describe: string = "$Intro"; | ||||||
|  | 
 | ||||||
|  |     public override category: string = "$Initiative"; | ||||||
|  | 
 | ||||||
|  | 	public override parameterOption = { | ||||||
|  | 		target: { type: "CLG", name: "$Target" }, | ||||||
|  |         range: { type: "number", name: "$Range", defaultValue: 4, numberMin: 0, numberStep: .1 }, | ||||||
|  |         angle: { type: "number", name: "$Angle", defaultValue: 180, numberMin: 0, numberMax: 360, numberStep: 5 }, | ||||||
|  | 		strength: { type: "number", name: "$Strength", defaultValue: 1, numberMin: 0, numberStep: .1 }, | ||||||
|  |         accuracy: { type: "number", name: "$Accuracy", defaultValue: 5, numberMin: 0, numberMax: 180, numberStep: 1 } | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  |     private angle2Vector(v1: number[], v2: number[]): number { | ||||||
|  | 		return Math.acos( | ||||||
|  | 			(v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]) / | ||||||
|  | 			( | ||||||
|  | 				(v1[0] ** 2 + v1[1] ** 2 + v1[2] ** 2) ** 0.5 * | ||||||
|  | 				(v2[0] ** 2 + v2[1] ** 2 + v2[2] ** 2) ** 0.5 | ||||||
|  | 			) | ||||||
|  | 		) * 180 / Math.PI; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  |     public effect = (individual: Individual, group: Group, model: Model, t: number): void => { | ||||||
|  | 
 | ||||||
|  |         const dirArr: number[][] = []; const valArr: number[] = []; | ||||||
|  | 
 | ||||||
|  |         for (let i = 0; i < this.parameter.target.objects.length; i++) { | ||||||
|  |             const targetGroup = this.parameter.target.objects[i]; | ||||||
|  | 
 | ||||||
|  | 			targetGroup.individuals.forEach((targetIndividual) => { | ||||||
|  | 
 | ||||||
|  |                 // 计算距离
 | ||||||
|  |                 let dis = targetIndividual.distanceTo(individual); | ||||||
|  |                 if (dis > this.parameter.range) return; | ||||||
|  | 
 | ||||||
|  |                 // 计算方向
 | ||||||
|  |                 let targetDir = [ | ||||||
|  |                     targetIndividual.position[0] - individual.position[0], | ||||||
|  |                     targetIndividual.position[1] - individual.position[1], | ||||||
|  |                     targetIndividual.position[2] - individual.position[2] | ||||||
|  |                 ]; | ||||||
|  | 
 | ||||||
|  |                 // 计算视线角度
 | ||||||
|  |                 let angle = this.angle2Vector(individual.velocity, targetDir); | ||||||
|  | 
 | ||||||
|  |                 // 在可视角度内
 | ||||||
|  |                 if (angle < (this.parameter.angle ?? 360) / 2) { | ||||||
|  | 
 | ||||||
|  |                     // 采样
 | ||||||
|  |                     let isFindNest = false; | ||||||
|  |                     for (let i = 0; i < valArr.length; i++) { | ||||||
|  | 
 | ||||||
|  |                         // 计算采样角度
 | ||||||
|  |                         let sampleAngle = this.angle2Vector(dirArr[i], targetDir); | ||||||
|  | 
 | ||||||
|  |                         // 小于采样精度,合并
 | ||||||
|  |                         if (sampleAngle < this.parameter.accuracy ?? 5) { | ||||||
|  |                             dirArr[i][0] += targetDir[0]; | ||||||
|  |                             dirArr[i][1] += targetDir[1]; | ||||||
|  |                             dirArr[i][2] += targetDir[2]; | ||||||
|  |                             valArr[i] += targetIndividual.getData("Wastage.Pheromone") ?? 0; | ||||||
|  |                             isFindNest = true; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     if (!isFindNest) { | ||||||
|  | 
 | ||||||
|  |                         // 保存
 | ||||||
|  |                         dirArr.push(targetDir); | ||||||
|  |                         valArr.push(targetIndividual.getData("Wastage.Pheromone") ?? 0); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 计算最大方向
 | ||||||
|  |         let maxVal = -1; let maxDir: number[] | undefined; | ||||||
|  |         for (let i = 0; i < valArr.length; i++) { | ||||||
|  |             if (valArr[i] > maxVal) { | ||||||
|  |                 maxVal = valArr[i]; | ||||||
|  |                 maxDir = dirArr[i]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (maxDir) { | ||||||
|  |             const dir = individual.vectorNormalize(maxDir); | ||||||
|  |             individual.applyForce( | ||||||
|  |                 dir[0] * this.parameter.strength, | ||||||
|  |                 dir[1] * this.parameter.strength, | ||||||
|  |                 dir[2] * this.parameter.strength | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	public override terms: Record<string, Record<string, string>> = { | ||||||
|  |         "$Title": { | ||||||
|  |             "ZH_CN": "采样追踪", | ||||||
|  |             "EN_US": "Sample tracking" | ||||||
|  |         }, | ||||||
|  | 		"$Target": { | ||||||
|  | 			"ZH_CN": "追踪目标", | ||||||
|  | 			"EN_US": "Tracking target" | ||||||
|  | 		}, | ||||||
|  |         "$Accuracy": { | ||||||
|  |             "ZH_CN": "采样精度", | ||||||
|  | 			"EN_US": "Sampling accuracy" | ||||||
|  |         }, | ||||||
|  |         "$Range": { | ||||||
|  |             "ZH_CN": "追踪范围 (m)", | ||||||
|  | 			"EN_US": "Tracking range (m)" | ||||||
|  |         }, | ||||||
|  | 		"$Strength": { | ||||||
|  | 			"ZH_CN": "追踪强度系数", | ||||||
|  | 			"EN_US": "Tracking intensity coefficient" | ||||||
|  | 		}, | ||||||
|  |         "$Intro": { | ||||||
|  |             "ZH_CN": "个体将主动向目标个体较多的方向发起追踪", | ||||||
|  |             "EN_US": "Individuals will actively initiate tracking in the direction of more target individuals" | ||||||
|  |         }, | ||||||
|  | 		"$Interactive": { | ||||||
|  | 			"ZH_CN": "交互", | ||||||
|  |             "EN_US": "Interactive" | ||||||
|  | 		}, | ||||||
|  |         "$Angle": { | ||||||
|  |             "ZH_CN": "可视角度", | ||||||
|  |             "EN_US": "Viewing angle" | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export { SampleTracking }; | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user