@holoscript/framework 6.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ALL-test-results.json +1 -0
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/ROADMAP.md +175 -0
- package/dist/AgentManifest-CB4xM-Ma.d.cts +704 -0
- package/dist/AgentManifest-CB4xM-Ma.d.ts +704 -0
- package/dist/BehaviorTree-BrBFECv5.d.cts +103 -0
- package/dist/BehaviorTree-BrBFECv5.d.ts +103 -0
- package/dist/InvisibleWallet-BB6tFvRA.d.cts +1732 -0
- package/dist/InvisibleWallet-rtRrBOA8.d.ts +1732 -0
- package/dist/OrchestratorAgent-BvWgf9uw.d.cts +798 -0
- package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +798 -0
- package/dist/agents/index.cjs +4790 -0
- package/dist/agents/index.d.cts +1788 -0
- package/dist/agents/index.d.ts +1788 -0
- package/dist/agents/index.js +4695 -0
- package/dist/ai/index.cjs +5347 -0
- package/dist/ai/index.d.cts +1753 -0
- package/dist/ai/index.d.ts +1753 -0
- package/dist/ai/index.js +5244 -0
- package/dist/behavior.cjs +449 -0
- package/dist/behavior.d.cts +130 -0
- package/dist/behavior.d.ts +130 -0
- package/dist/behavior.js +407 -0
- package/dist/economy/index.cjs +3659 -0
- package/dist/economy/index.d.cts +747 -0
- package/dist/economy/index.d.ts +747 -0
- package/dist/economy/index.js +3617 -0
- package/dist/implementations-D9T3un9D.d.cts +236 -0
- package/dist/implementations-D9T3un9D.d.ts +236 -0
- package/dist/index.cjs +24550 -0
- package/dist/index.d.cts +1729 -0
- package/dist/index.d.ts +1729 -0
- package/dist/index.js +24277 -0
- package/dist/learning/index.cjs +219 -0
- package/dist/learning/index.d.cts +104 -0
- package/dist/learning/index.d.ts +104 -0
- package/dist/learning/index.js +189 -0
- package/dist/negotiation/index.cjs +970 -0
- package/dist/negotiation/index.d.cts +610 -0
- package/dist/negotiation/index.d.ts +610 -0
- package/dist/negotiation/index.js +931 -0
- package/dist/skills/index.cjs +1118 -0
- package/dist/skills/index.d.cts +289 -0
- package/dist/skills/index.d.ts +289 -0
- package/dist/skills/index.js +1079 -0
- package/dist/swarm/index.cjs +5268 -0
- package/dist/swarm/index.d.cts +2433 -0
- package/dist/swarm/index.d.ts +2433 -0
- package/dist/swarm/index.js +5221 -0
- package/dist/training/index.cjs +2745 -0
- package/dist/training/index.d.cts +1734 -0
- package/dist/training/index.d.ts +1734 -0
- package/dist/training/index.js +2687 -0
- package/extract-failures.js +10 -0
- package/package.json +82 -0
- package/src/__tests__/bounty-marketplace.test.ts +374 -0
- package/src/__tests__/delegation.test.ts +144 -0
- package/src/__tests__/distributed-claimer.test.ts +147 -0
- package/src/__tests__/done-log-audit.test.ts +342 -0
- package/src/__tests__/framework.test.ts +865 -0
- package/src/__tests__/goal-synthesizer.test.ts +236 -0
- package/src/__tests__/presence.test.ts +223 -0
- package/src/__tests__/protocol-agent.test.ts +254 -0
- package/src/__tests__/revenue-splitter.test.ts +114 -0
- package/src/__tests__/scenario-driven-todo.test.ts +197 -0
- package/src/__tests__/self-improve.test.ts +349 -0
- package/src/__tests__/service-lifecycle.test.ts +237 -0
- package/src/__tests__/skill-router.test.ts +121 -0
- package/src/agents/AgentManifest.ts +493 -0
- package/src/agents/AgentRegistry.ts +475 -0
- package/src/agents/AgentTypes.ts +585 -0
- package/src/agents/AgentWalletRegistry.ts +83 -0
- package/src/agents/AuthenticatedCRDT.ts +388 -0
- package/src/agents/CapabilityMatcher.ts +453 -0
- package/src/agents/CrossRealityHandoff.ts +305 -0
- package/src/agents/CulturalMemory.ts +454 -0
- package/src/agents/FederatedRegistryAdapter.ts +429 -0
- package/src/agents/NormEngine.ts +450 -0
- package/src/agents/OrchestratorAgent.ts +414 -0
- package/src/agents/SkillWorkflowEngine.ts +472 -0
- package/src/agents/TaskDelegationService.ts +551 -0
- package/src/agents/__tests__/AgentManifest.prod.test.ts +134 -0
- package/src/agents/__tests__/AgentManifest.test.ts +182 -0
- package/src/agents/__tests__/AgentModule.test.ts +864 -0
- package/src/agents/__tests__/AgentRegistry.prod.test.ts +125 -0
- package/src/agents/__tests__/AgentRegistry.test.ts +148 -0
- package/src/agents/__tests__/AgentTypes.test.ts +534 -0
- package/src/agents/__tests__/AgentWalletRegistry.test.ts +152 -0
- package/src/agents/__tests__/AuthenticatedCRDT.test.ts +558 -0
- package/src/agents/__tests__/CapabilityMatcher.prod.test.ts +117 -0
- package/src/agents/__tests__/CapabilityMatcher.test.ts +178 -0
- package/src/agents/__tests__/CrossRealityHandoff.test.ts +402 -0
- package/src/agents/__tests__/CulturalMemory.test.ts +200 -0
- package/src/agents/__tests__/FederatedRegistryAdapter.test.ts +409 -0
- package/src/agents/__tests__/NormEngine.test.ts +276 -0
- package/src/agents/__tests__/OrchestratorAgent.test.ts +182 -0
- package/src/agents/__tests__/SkillWorkflowEngine.test.ts +357 -0
- package/src/agents/__tests__/TaskDelegationService.test.ts +446 -0
- package/src/agents/index.ts +107 -0
- package/src/agents/spatial-comms/Layer1RealTime.ts +621 -0
- package/src/agents/spatial-comms/Layer2A2A.ts +661 -0
- package/src/agents/spatial-comms/Layer3MCP.ts +651 -0
- package/src/agents/spatial-comms/ProtocolTypes.ts +543 -0
- package/src/agents/spatial-comms/SpatialCommClient.ts +483 -0
- package/src/agents/spatial-comms/__tests__/performance-benchmark.test.ts +465 -0
- package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +409 -0
- package/src/agents/spatial-comms/index.ts +66 -0
- package/src/ai/AIAdapter.ts +313 -0
- package/src/ai/AICopilot.ts +331 -0
- package/src/ai/AIOutputValidator.ts +203 -0
- package/src/ai/BTNodes.ts +239 -0
- package/src/ai/BehaviorSelector.ts +135 -0
- package/src/ai/BehaviorTree.ts +153 -0
- package/src/ai/Blackboard.ts +165 -0
- package/src/ai/GenerationAnalytics.ts +461 -0
- package/src/ai/GenerationCache.ts +265 -0
- package/src/ai/GoalPlanner.ts +165 -0
- package/src/ai/HoloScriptGenerator.ts +580 -0
- package/src/ai/InfluenceMap.ts +180 -0
- package/src/ai/NavMesh.ts +168 -0
- package/src/ai/PerceptionSystem.ts +178 -0
- package/src/ai/PromptTemplates.ts +453 -0
- package/src/ai/SemanticSearchService.ts +80 -0
- package/src/ai/StateMachine.ts +196 -0
- package/src/ai/SteeringBehavior.ts +150 -0
- package/src/ai/SteeringBehaviors.ts +244 -0
- package/src/ai/TrainingDataGenerator.ts +1082 -0
- package/src/ai/UtilityAI.ts +145 -0
- package/src/ai/__tests__/AIAdapter.prod.test.ts +259 -0
- package/src/ai/__tests__/AIAdapter.test.ts +109 -0
- package/src/ai/__tests__/AICopilot.prod.test.ts +341 -0
- package/src/ai/__tests__/AICopilot.test.ts +178 -0
- package/src/ai/__tests__/AIOutputValidator.prod.test.ts +226 -0
- package/src/ai/__tests__/AIOutputValidator.test.ts +138 -0
- package/src/ai/__tests__/BTNodes.prod.test.ts +391 -0
- package/src/ai/__tests__/BTNodes.test.ts +263 -0
- package/src/ai/__tests__/BehaviorSelector.prod.test.ts +129 -0
- package/src/ai/__tests__/BehaviorSelector.test.ts +132 -0
- package/src/ai/__tests__/BehaviorTree.prod.test.ts +266 -0
- package/src/ai/__tests__/BehaviorTree.test.ts +216 -0
- package/src/ai/__tests__/Blackboard.prod.test.ts +339 -0
- package/src/ai/__tests__/Blackboard.test.ts +183 -0
- package/src/ai/__tests__/GenerationAnalytics.prod.test.ts +141 -0
- package/src/ai/__tests__/GenerationAnalytics.test.ts +165 -0
- package/src/ai/__tests__/GenerationCache.prod.test.ts +144 -0
- package/src/ai/__tests__/GenerationCache.test.ts +171 -0
- package/src/ai/__tests__/GoalPlanner.prod.test.ts +189 -0
- package/src/ai/__tests__/GoalPlanner.test.ts +137 -0
- package/src/ai/__tests__/GoalPlannerDepth.prod.test.ts +217 -0
- package/src/ai/__tests__/HoloScriptGenerator.test.ts +125 -0
- package/src/ai/__tests__/InfluenceMap.prod.test.ts +146 -0
- package/src/ai/__tests__/InfluenceMap.test.ts +149 -0
- package/src/ai/__tests__/NavMesh.prod.test.ts +141 -0
- package/src/ai/__tests__/NavMesh.test.ts +159 -0
- package/src/ai/__tests__/PerceptionSystem.prod.test.ts +135 -0
- package/src/ai/__tests__/PerceptionSystem.test.ts +250 -0
- package/src/ai/__tests__/PromptTemplates.prod.test.ts +313 -0
- package/src/ai/__tests__/PromptTemplates.test.ts +146 -0
- package/src/ai/__tests__/SemanticSearch.test.ts +37 -0
- package/src/ai/__tests__/StateMachine.prod.test.ts +162 -0
- package/src/ai/__tests__/StateMachine.test.ts +163 -0
- package/src/ai/__tests__/SteeringBehavior.prod.test.ts +251 -0
- package/src/ai/__tests__/SteeringBehavior.test.ts +135 -0
- package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +133 -0
- package/src/ai/__tests__/SteeringBehaviors.test.ts +151 -0
- package/src/ai/__tests__/TrainingDataGenerator.prod.test.ts +286 -0
- package/src/ai/__tests__/TrainingDataGenerator.test.ts +286 -0
- package/src/ai/__tests__/UtilityAI.prod.test.ts +207 -0
- package/src/ai/__tests__/UtilityAI.test.ts +155 -0
- package/src/ai/__tests__/adapters.prod.test.ts +263 -0
- package/src/ai/__tests__/adapters.test.ts +320 -0
- package/src/ai/adapters.ts +1585 -0
- package/src/ai/index.ts +130 -0
- package/src/behavior/BehaviorPresets.ts +140 -0
- package/src/behavior/BehaviorTree.ts +236 -0
- package/src/behavior/StateMachine.ts +176 -0
- package/src/behavior/StateTrait.ts +67 -0
- package/src/behavior/index.ts +8 -0
- package/src/behavior.ts +8 -0
- package/src/board/audit.ts +284 -0
- package/src/board/board-ops.ts +336 -0
- package/src/board/board-types.ts +302 -0
- package/src/board/index.ts +69 -0
- package/src/define-agent.ts +46 -0
- package/src/define-team.ts +33 -0
- package/src/delegation.ts +265 -0
- package/src/distributed-claimer.ts +228 -0
- package/src/economy/AgentBudgetEnforcer.ts +464 -0
- package/src/economy/BountyManager.ts +185 -0
- package/src/economy/CreatorRevenueAggregator.ts +460 -0
- package/src/economy/InvisibleWallet.ts +82 -0
- package/src/economy/KnowledgeMarketplace.ts +193 -0
- package/src/economy/PaymentWebhookService.ts +512 -0
- package/src/economy/RevenueSplitter.ts +156 -0
- package/src/economy/SubscriptionManager.ts +546 -0
- package/src/economy/UnifiedBudgetOptimizer.ts +635 -0
- package/src/economy/UsageMeter.ts +440 -0
- package/src/economy/_core-stubs.ts +219 -0
- package/src/economy/index.ts +100 -0
- package/src/economy/x402-facilitator.ts +1978 -0
- package/src/index.ts +348 -0
- package/src/knowledge/__tests__/knowledge-consolidator.test.ts +444 -0
- package/src/knowledge/__tests__/knowledge-store-vector.test.ts +291 -0
- package/src/knowledge/brain.ts +167 -0
- package/src/knowledge/consolidation.ts +581 -0
- package/src/knowledge/knowledge-consolidator.ts +510 -0
- package/src/knowledge/knowledge-store.ts +616 -0
- package/src/learning/MemoryConsolidator.ts +102 -0
- package/src/learning/MemoryScorer.ts +69 -0
- package/src/learning/ProceduralCompiler.ts +45 -0
- package/src/learning/SemanticClusterer.ts +66 -0
- package/src/learning/index.ts +8 -0
- package/src/llm/llm-adapter.ts +159 -0
- package/src/mesh/index.ts +309 -0
- package/src/negotiation/NegotiationProtocol.ts +694 -0
- package/src/negotiation/NegotiationTypes.ts +473 -0
- package/src/negotiation/VotingMechanisms.ts +691 -0
- package/src/negotiation/index.ts +49 -0
- package/src/protocol/goal-synthesizer.ts +317 -0
- package/src/protocol/implementations.ts +474 -0
- package/src/protocol/micro-phase-decomposer.ts +299 -0
- package/src/protocol/micro-step-decomposer.test.ts +306 -0
- package/src/protocol-agent.test.ts +353 -0
- package/src/protocol-agent.ts +670 -0
- package/src/self-improve/absorb-scanner.ts +252 -0
- package/src/self-improve/evolution-engine.ts +149 -0
- package/src/self-improve/framework-absorber.ts +214 -0
- package/src/self-improve/index.ts +50 -0
- package/src/self-improve/prompt-optimizer.ts +212 -0
- package/src/self-improve/test-generator.ts +175 -0
- package/src/skill-router.ts +186 -0
- package/src/skills/index.ts +5 -0
- package/src/skills/skill-md-bridge.ts +1699 -0
- package/src/swarm/ACOEngine.ts +261 -0
- package/src/swarm/CollectiveIntelligence.ts +383 -0
- package/src/swarm/ContributionSynthesizer.ts +481 -0
- package/src/swarm/LeaderElection.ts +393 -0
- package/src/swarm/PSOEngine.ts +206 -0
- package/src/swarm/QuorumPolicy.ts +173 -0
- package/src/swarm/SwarmCoordinator.ts +335 -0
- package/src/swarm/SwarmManager.ts +442 -0
- package/src/swarm/SwarmMembership.ts +456 -0
- package/src/swarm/VotingRound.ts +255 -0
- package/src/swarm/__tests__/ACOEngine.prod.test.ts +164 -0
- package/src/swarm/__tests__/ACOEngine.test.ts +117 -0
- package/src/swarm/__tests__/CollectiveIntelligence.prod.test.ts +296 -0
- package/src/swarm/__tests__/CollectiveIntelligence.test.ts +457 -0
- package/src/swarm/__tests__/ContributionSynthesizer.prod.test.ts +269 -0
- package/src/swarm/__tests__/ContributionSynthesizer.test.ts +254 -0
- package/src/swarm/__tests__/LeaderElection.prod.test.ts +196 -0
- package/src/swarm/__tests__/LeaderElection.test.ts +151 -0
- package/src/swarm/__tests__/PSOEngine.prod.test.ts +162 -0
- package/src/swarm/__tests__/PSOEngine.test.ts +106 -0
- package/src/swarm/__tests__/QuorumPolicy.prod.test.ts +216 -0
- package/src/swarm/__tests__/QuorumPolicy.test.ts +177 -0
- package/src/swarm/__tests__/SwarmCoordinator.prod.test.ts +186 -0
- package/src/swarm/__tests__/SwarmCoordinator.test.ts +167 -0
- package/src/swarm/__tests__/SwarmManager.prod.test.ts +308 -0
- package/src/swarm/__tests__/SwarmManager.test.ts +373 -0
- package/src/swarm/__tests__/SwarmMembership.prod.test.ts +273 -0
- package/src/swarm/__tests__/SwarmMembership.test.ts +264 -0
- package/src/swarm/__tests__/VotingRound.prod.test.ts +233 -0
- package/src/swarm/__tests__/VotingRound.test.ts +174 -0
- package/src/swarm/analytics/SwarmInspector.ts +476 -0
- package/src/swarm/analytics/SwarmMetrics.ts +449 -0
- package/src/swarm/analytics/__tests__/SwarmInspector.prod.test.ts +366 -0
- package/src/swarm/analytics/__tests__/SwarmInspector.test.ts +454 -0
- package/src/swarm/analytics/__tests__/SwarmMetrics.prod.test.ts +254 -0
- package/src/swarm/analytics/__tests__/SwarmMetrics.test.ts +370 -0
- package/src/swarm/analytics/index.ts +7 -0
- package/src/swarm/index.ts +69 -0
- package/src/swarm/messaging/BroadcastChannel.ts +509 -0
- package/src/swarm/messaging/GossipProtocol.ts +565 -0
- package/src/swarm/messaging/SwarmEventBus.ts +443 -0
- package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +331 -0
- package/src/swarm/messaging/__tests__/BroadcastChannel.test.ts +333 -0
- package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +356 -0
- package/src/swarm/messaging/__tests__/GossipProtocol.test.ts +437 -0
- package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +191 -0
- package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +247 -0
- package/src/swarm/messaging/index.ts +8 -0
- package/src/swarm/spatial/FlockingBehavior.ts +462 -0
- package/src/swarm/spatial/FormationController.ts +500 -0
- package/src/swarm/spatial/Vector3.ts +170 -0
- package/src/swarm/spatial/ZoneClaiming.ts +509 -0
- package/src/swarm/spatial/__tests__/FlockingBehavior.prod.test.ts +239 -0
- package/src/swarm/spatial/__tests__/FlockingBehavior.test.ts +298 -0
- package/src/swarm/spatial/__tests__/FormationController.prod.test.ts +240 -0
- package/src/swarm/spatial/__tests__/FormationController.test.ts +297 -0
- package/src/swarm/spatial/__tests__/Vector3.prod.test.ts +283 -0
- package/src/swarm/spatial/__tests__/Vector3.test.ts +224 -0
- package/src/swarm/spatial/__tests__/ZoneClaiming.prod.test.ts +246 -0
- package/src/swarm/spatial/__tests__/ZoneClaiming.test.ts +374 -0
- package/src/swarm/spatial/index.ts +28 -0
- package/src/team.ts +1245 -0
- package/src/training/LRScheduler.ts +377 -0
- package/src/training/QualityScoringPipeline.ts +139 -0
- package/src/training/SoftDedup.ts +461 -0
- package/src/training/SparsityMonitor.ts +685 -0
- package/src/training/SparsityMonitorTypes.ts +209 -0
- package/src/training/SpatialTrainingDataGenerator.ts +1526 -0
- package/src/training/SpatialTrainingDataTypes.ts +216 -0
- package/src/training/TrainingPipelineConfig.ts +215 -0
- package/src/training/constants.ts +94 -0
- package/src/training/index.ts +138 -0
- package/src/training/schema.ts +147 -0
- package/src/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
- package/src/training/scripts/generate-spatial-dataset.ts +521 -0
- package/src/training/training/data/novel-use-cases.jsonl +153 -0
- package/src/training/training/data/spatial-reasoning-10k.jsonl +9354 -0
- package/src/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
- package/src/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
- package/src/training/trainingmonkey/index.ts +26 -0
- package/src/training/trait-mappings.ts +157 -0
- package/src/types/core-stubs.d.ts +113 -0
- package/src/types.ts +304 -0
- package/test-output.txt +0 -0
- package/test-result.json +1 -0
- package/tsc-errors.txt +4 -0
- package/tsc_output.txt +0 -0
- package/tsconfig.json +14 -0
- package/tsup-learning-esm.config.ts +12 -0
- package/tsup.config.ts +21 -0
- package/typescript-errors-2.txt +0 -0
- package/typescript-errors.txt +22 -0
- package/vitest-log-utf8.txt +268 -0
- package/vitest-log.txt +0 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FormationController - Geometric swarm formations
|
|
3
|
+
* HoloScript v3.2 - Autonomous Agent Swarms
|
|
4
|
+
*
|
|
5
|
+
* Manages precise geometric arrangements of swarm agents
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Vector3 } from './Vector3';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Formation patterns
|
|
12
|
+
*/
|
|
13
|
+
export type FormationType = 'line' | 'circle' | 'grid' | 'wedge' | 'diamond' | 'sphere' | 'custom';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Formation slot - assigned position for an agent
|
|
17
|
+
*/
|
|
18
|
+
export interface IFormationSlot {
|
|
19
|
+
index: number;
|
|
20
|
+
agentId: string | null;
|
|
21
|
+
localPosition: Vector3;
|
|
22
|
+
worldPosition: Vector3;
|
|
23
|
+
isLeaderSlot: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Formation configuration
|
|
28
|
+
*/
|
|
29
|
+
export interface IFormationConfig {
|
|
30
|
+
type: FormationType;
|
|
31
|
+
spacing: number;
|
|
32
|
+
orientation: Vector3;
|
|
33
|
+
scale: number;
|
|
34
|
+
centerOffset: Vector3;
|
|
35
|
+
rotationAngle: number; // Radians around Y axis
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* FormationController - Manages geometric swarm formations
|
|
40
|
+
*/
|
|
41
|
+
export class FormationController {
|
|
42
|
+
private slots: Map<number, IFormationSlot> = new Map();
|
|
43
|
+
private agentSlots: Map<string, number> = new Map();
|
|
44
|
+
private center: Vector3 = Vector3.zero();
|
|
45
|
+
private config: IFormationConfig;
|
|
46
|
+
private slotCount: number = 0;
|
|
47
|
+
|
|
48
|
+
constructor(config?: Partial<IFormationConfig>) {
|
|
49
|
+
this.config = {
|
|
50
|
+
type: 'line',
|
|
51
|
+
spacing: 2,
|
|
52
|
+
orientation: new Vector3(0, 0, 1),
|
|
53
|
+
scale: 1,
|
|
54
|
+
centerOffset: Vector3.zero(),
|
|
55
|
+
rotationAngle: 0,
|
|
56
|
+
...config,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generate formation slots for given count
|
|
62
|
+
*/
|
|
63
|
+
generateSlots(count: number): IFormationSlot[] {
|
|
64
|
+
this.slots.clear();
|
|
65
|
+
this.slotCount = count;
|
|
66
|
+
|
|
67
|
+
let positions: Vector3[] = [];
|
|
68
|
+
|
|
69
|
+
switch (this.config.type) {
|
|
70
|
+
case 'line':
|
|
71
|
+
positions = this.generateLineFormation(count);
|
|
72
|
+
break;
|
|
73
|
+
case 'circle':
|
|
74
|
+
positions = this.generateCircleFormation(count);
|
|
75
|
+
break;
|
|
76
|
+
case 'grid':
|
|
77
|
+
positions = this.generateGridFormation(count);
|
|
78
|
+
break;
|
|
79
|
+
case 'wedge':
|
|
80
|
+
positions = this.generateWedgeFormation(count);
|
|
81
|
+
break;
|
|
82
|
+
case 'diamond':
|
|
83
|
+
positions = this.generateDiamondFormation(count);
|
|
84
|
+
break;
|
|
85
|
+
case 'sphere':
|
|
86
|
+
positions = this.generateSphereFormation(count);
|
|
87
|
+
break;
|
|
88
|
+
default:
|
|
89
|
+
positions = this.generateLineFormation(count);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Create slots from positions
|
|
93
|
+
for (let i = 0; i < positions.length; i++) {
|
|
94
|
+
const slot: IFormationSlot = {
|
|
95
|
+
index: i,
|
|
96
|
+
agentId: null,
|
|
97
|
+
localPosition: positions[i],
|
|
98
|
+
worldPosition: this.localToWorld(positions[i]),
|
|
99
|
+
isLeaderSlot: i === 0,
|
|
100
|
+
};
|
|
101
|
+
this.slots.set(i, slot);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return this.getAllSlots();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Line formation - agents in a row
|
|
109
|
+
*/
|
|
110
|
+
private generateLineFormation(count: number): Vector3[] {
|
|
111
|
+
const positions: Vector3[] = [];
|
|
112
|
+
const startOffset = -((count - 1) * this.config.spacing) / 2;
|
|
113
|
+
|
|
114
|
+
for (let i = 0; i < count; i++) {
|
|
115
|
+
positions.push(new Vector3(startOffset + i * this.config.spacing, 0, 0));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return positions;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Circle formation - agents in a ring
|
|
123
|
+
*/
|
|
124
|
+
private generateCircleFormation(count: number): Vector3[] {
|
|
125
|
+
const positions: Vector3[] = [];
|
|
126
|
+
const radius = (count * this.config.spacing) / (2 * Math.PI);
|
|
127
|
+
|
|
128
|
+
for (let i = 0; i < count; i++) {
|
|
129
|
+
const angle = (2 * Math.PI * i) / count;
|
|
130
|
+
positions.push(new Vector3(Math.cos(angle) * radius, 0, Math.sin(angle) * radius));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return positions;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Grid formation - agents in rows and columns
|
|
138
|
+
*/
|
|
139
|
+
private generateGridFormation(count: number): Vector3[] {
|
|
140
|
+
const positions: Vector3[] = [];
|
|
141
|
+
const cols = Math.ceil(Math.sqrt(count));
|
|
142
|
+
const rows = Math.ceil(count / cols);
|
|
143
|
+
|
|
144
|
+
const xOffset = -((cols - 1) * this.config.spacing) / 2;
|
|
145
|
+
const zOffset = -((rows - 1) * this.config.spacing) / 2;
|
|
146
|
+
|
|
147
|
+
let index = 0;
|
|
148
|
+
for (let row = 0; row < rows && index < count; row++) {
|
|
149
|
+
for (let col = 0; col < cols && index < count; col++) {
|
|
150
|
+
positions.push(
|
|
151
|
+
new Vector3(xOffset + col * this.config.spacing, 0, zOffset + row * this.config.spacing)
|
|
152
|
+
);
|
|
153
|
+
index++;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return positions;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Wedge formation - V-shaped, leader at point
|
|
162
|
+
*/
|
|
163
|
+
private generateWedgeFormation(count: number): Vector3[] {
|
|
164
|
+
const positions: Vector3[] = [];
|
|
165
|
+
|
|
166
|
+
// Leader at front
|
|
167
|
+
positions.push(Vector3.zero());
|
|
168
|
+
|
|
169
|
+
let row = 1;
|
|
170
|
+
let placed = 1;
|
|
171
|
+
|
|
172
|
+
while (placed < count) {
|
|
173
|
+
// Left and right of each row
|
|
174
|
+
for (let side = 0; side < 2 && placed < count; side++) {
|
|
175
|
+
const x = (side === 0 ? -1 : 1) * row * this.config.spacing * 0.5;
|
|
176
|
+
const z = -row * this.config.spacing;
|
|
177
|
+
positions.push(new Vector3(x, 0, z));
|
|
178
|
+
placed++;
|
|
179
|
+
}
|
|
180
|
+
row++;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return positions;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Diamond formation - diamond shape, leader at front point
|
|
188
|
+
*/
|
|
189
|
+
private generateDiamondFormation(count: number): Vector3[] {
|
|
190
|
+
const positions: Vector3[] = [];
|
|
191
|
+
|
|
192
|
+
// Calculate diamond dimensions
|
|
193
|
+
const n = Math.ceil(Math.sqrt(2 * count + 0.25) - 0.5);
|
|
194
|
+
let placed = 0;
|
|
195
|
+
|
|
196
|
+
// Top half (expanding)
|
|
197
|
+
for (let row = 0; row <= n && placed < count; row++) {
|
|
198
|
+
const rowWidth = row + 1;
|
|
199
|
+
const xOffset = -(row * this.config.spacing) / 2;
|
|
200
|
+
const z = -row * this.config.spacing;
|
|
201
|
+
|
|
202
|
+
for (let i = 0; i < rowWidth && placed < count; i++) {
|
|
203
|
+
positions.push(new Vector3(xOffset + i * this.config.spacing, 0, z));
|
|
204
|
+
placed++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Bottom half (contracting)
|
|
209
|
+
for (let row = n - 1; row >= 0 && placed < count; row--) {
|
|
210
|
+
const rowWidth = row + 1;
|
|
211
|
+
const xOffset = -(row * this.config.spacing) / 2;
|
|
212
|
+
const z = (n - row) * this.config.spacing;
|
|
213
|
+
|
|
214
|
+
for (let i = 0; i < rowWidth && placed < count; i++) {
|
|
215
|
+
positions.push(new Vector3(xOffset + i * this.config.spacing, 0, z));
|
|
216
|
+
placed++;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return positions;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Sphere formation - 3D spherical arrangement
|
|
225
|
+
*/
|
|
226
|
+
private generateSphereFormation(count: number): Vector3[] {
|
|
227
|
+
const positions: Vector3[] = [];
|
|
228
|
+
const radius = (this.config.spacing * Math.cbrt(count)) / 2;
|
|
229
|
+
|
|
230
|
+
// Use Fibonacci sphere algorithm for even distribution
|
|
231
|
+
const goldenAngle = Math.PI * (3 - Math.sqrt(5));
|
|
232
|
+
|
|
233
|
+
for (let i = 0; i < count; i++) {
|
|
234
|
+
const y = 1 - (i / (count - 1)) * 2;
|
|
235
|
+
const radiusAtY = Math.sqrt(1 - y * y);
|
|
236
|
+
const theta = goldenAngle * i;
|
|
237
|
+
|
|
238
|
+
positions.push(
|
|
239
|
+
new Vector3(
|
|
240
|
+
Math.cos(theta) * radiusAtY * radius,
|
|
241
|
+
y * radius,
|
|
242
|
+
Math.sin(theta) * radiusAtY * radius
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return positions;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Set custom formation positions
|
|
252
|
+
*/
|
|
253
|
+
setCustomFormation(positions: Vector3[]): void {
|
|
254
|
+
this.config.type = 'custom';
|
|
255
|
+
this.slots.clear();
|
|
256
|
+
this.slotCount = positions.length;
|
|
257
|
+
|
|
258
|
+
for (let i = 0; i < positions.length; i++) {
|
|
259
|
+
const slot: IFormationSlot = {
|
|
260
|
+
index: i,
|
|
261
|
+
agentId: null,
|
|
262
|
+
localPosition: positions[i],
|
|
263
|
+
worldPosition: this.localToWorld(positions[i]),
|
|
264
|
+
isLeaderSlot: i === 0,
|
|
265
|
+
};
|
|
266
|
+
this.slots.set(i, slot);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Assign an agent to a slot
|
|
272
|
+
*/
|
|
273
|
+
assignAgent(agentId: string, slotIndex?: number): number {
|
|
274
|
+
// If slot specified, try to use it
|
|
275
|
+
if (slotIndex !== undefined) {
|
|
276
|
+
const slot = this.slots.get(slotIndex);
|
|
277
|
+
if (slot && slot.agentId === null) {
|
|
278
|
+
slot.agentId = agentId;
|
|
279
|
+
this.agentSlots.set(agentId, slotIndex);
|
|
280
|
+
return slotIndex;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Find first available slot
|
|
285
|
+
for (const [index, slot] of this.slots) {
|
|
286
|
+
if (slot.agentId === null) {
|
|
287
|
+
slot.agentId = agentId;
|
|
288
|
+
this.agentSlots.set(agentId, index);
|
|
289
|
+
return index;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return -1; // No slots available
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Remove an agent from its slot
|
|
298
|
+
*/
|
|
299
|
+
removeAgent(agentId: string): boolean {
|
|
300
|
+
const slotIndex = this.agentSlots.get(agentId);
|
|
301
|
+
if (slotIndex === undefined) return false;
|
|
302
|
+
|
|
303
|
+
const slot = this.slots.get(slotIndex);
|
|
304
|
+
if (slot) {
|
|
305
|
+
slot.agentId = null;
|
|
306
|
+
}
|
|
307
|
+
this.agentSlots.delete(agentId);
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Get agent's assigned slot
|
|
313
|
+
*/
|
|
314
|
+
getAgentSlot(agentId: string): IFormationSlot | undefined {
|
|
315
|
+
const slotIndex = this.agentSlots.get(agentId);
|
|
316
|
+
if (slotIndex === undefined) return undefined;
|
|
317
|
+
return this.slots.get(slotIndex);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Get target position for an agent
|
|
322
|
+
*/
|
|
323
|
+
getAgentTarget(agentId: string): Vector3 | undefined {
|
|
324
|
+
const slot = this.getAgentSlot(agentId);
|
|
325
|
+
return slot?.worldPosition;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Get all slots
|
|
330
|
+
*/
|
|
331
|
+
getAllSlots(): IFormationSlot[] {
|
|
332
|
+
return [...this.slots.values()];
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Get available (unassigned) slots
|
|
337
|
+
*/
|
|
338
|
+
getAvailableSlots(): IFormationSlot[] {
|
|
339
|
+
return this.getAllSlots().filter((s) => s.agentId === null);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Get assigned slots
|
|
344
|
+
*/
|
|
345
|
+
getAssignedSlots(): IFormationSlot[] {
|
|
346
|
+
return this.getAllSlots().filter((s) => s.agentId !== null);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Set formation center position
|
|
351
|
+
*/
|
|
352
|
+
setCenter(position: Vector3): void {
|
|
353
|
+
this.center = position.clone();
|
|
354
|
+
this.updateWorldPositions();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Get formation center
|
|
359
|
+
*/
|
|
360
|
+
getCenter(): Vector3 {
|
|
361
|
+
return this.center.clone();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Set rotation angle
|
|
366
|
+
*/
|
|
367
|
+
setRotation(angle: number): void {
|
|
368
|
+
this.config.rotationAngle = angle;
|
|
369
|
+
this.updateWorldPositions();
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Update world positions based on center and rotation
|
|
374
|
+
*/
|
|
375
|
+
private updateWorldPositions(): void {
|
|
376
|
+
for (const slot of this.slots.values()) {
|
|
377
|
+
slot.worldPosition = this.localToWorld(slot.localPosition);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Convert local position to world position
|
|
383
|
+
*/
|
|
384
|
+
private localToWorld(local: Vector3): Vector3 {
|
|
385
|
+
// Apply scale
|
|
386
|
+
let pos = local.multiply(this.config.scale);
|
|
387
|
+
|
|
388
|
+
// Apply rotation around Y axis
|
|
389
|
+
if (this.config.rotationAngle !== 0) {
|
|
390
|
+
const cos = Math.cos(this.config.rotationAngle);
|
|
391
|
+
const sin = Math.sin(this.config.rotationAngle);
|
|
392
|
+
const newX = pos.x * cos - pos.z * sin;
|
|
393
|
+
const newZ = pos.x * sin + pos.z * cos;
|
|
394
|
+
pos = new Vector3(newX, pos.y, newZ);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Apply center offset and formation offset
|
|
398
|
+
return pos.add(this.center).add(this.config.centerOffset);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Check if formation is complete (all slots filled)
|
|
403
|
+
*/
|
|
404
|
+
isComplete(): boolean {
|
|
405
|
+
return this.getAvailableSlots().length === 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Get formation completeness ratio
|
|
410
|
+
*/
|
|
411
|
+
getCompletenessRatio(): number {
|
|
412
|
+
if (this.slots.size === 0) return 0;
|
|
413
|
+
return this.getAssignedSlots().length / this.slots.size;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Get formation tightness (average distance from target)
|
|
418
|
+
*/
|
|
419
|
+
getFormationTightness(agentPositions: Map<string, Vector3>): number {
|
|
420
|
+
const assigned = this.getAssignedSlots();
|
|
421
|
+
if (assigned.length === 0) return 1;
|
|
422
|
+
|
|
423
|
+
let totalError = 0;
|
|
424
|
+
let count = 0;
|
|
425
|
+
|
|
426
|
+
for (const slot of assigned) {
|
|
427
|
+
if (slot.agentId) {
|
|
428
|
+
const actual = agentPositions.get(slot.agentId);
|
|
429
|
+
if (actual) {
|
|
430
|
+
const error = actual.distanceTo(slot.worldPosition);
|
|
431
|
+
totalError += error;
|
|
432
|
+
count++;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (count === 0) return 1;
|
|
438
|
+
|
|
439
|
+
// Convert error to tightness (1 = perfect, 0 = very loose)
|
|
440
|
+
const avgError = totalError / count;
|
|
441
|
+
return Math.max(0, 1 - avgError / this.config.spacing);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Reoptimize slot assignments (minimize total distance)
|
|
446
|
+
*/
|
|
447
|
+
optimizeAssignments(agentPositions: Map<string, Vector3>): void {
|
|
448
|
+
const agents = [...agentPositions.entries()];
|
|
449
|
+
const slots = this.getAllSlots();
|
|
450
|
+
|
|
451
|
+
// Clear current assignments
|
|
452
|
+
for (const slot of slots) {
|
|
453
|
+
if (slot.agentId) {
|
|
454
|
+
this.agentSlots.delete(slot.agentId);
|
|
455
|
+
slot.agentId = null;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Greedy assignment: closest agent to each slot
|
|
460
|
+
const assignedAgents = new Set<string>();
|
|
461
|
+
|
|
462
|
+
for (const slot of slots) {
|
|
463
|
+
let bestAgent: string | null = null;
|
|
464
|
+
let bestDist = Infinity;
|
|
465
|
+
|
|
466
|
+
for (const [agentId, position] of agents) {
|
|
467
|
+
if (assignedAgents.has(agentId)) continue;
|
|
468
|
+
|
|
469
|
+
const dist = position.distanceTo(slot.worldPosition);
|
|
470
|
+
if (dist < bestDist) {
|
|
471
|
+
bestDist = dist;
|
|
472
|
+
bestAgent = agentId;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (bestAgent) {
|
|
477
|
+
slot.agentId = bestAgent;
|
|
478
|
+
this.agentSlots.set(bestAgent, slot.index);
|
|
479
|
+
assignedAgents.add(bestAgent);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Update configuration
|
|
486
|
+
*/
|
|
487
|
+
setConfig(config: Partial<IFormationConfig>): void {
|
|
488
|
+
this.config = { ...this.config, ...config };
|
|
489
|
+
if (this.slotCount > 0) {
|
|
490
|
+
this.generateSlots(this.slotCount);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Get current configuration
|
|
496
|
+
*/
|
|
497
|
+
getConfig(): IFormationConfig {
|
|
498
|
+
return { ...this.config };
|
|
499
|
+
}
|
|
500
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector3 - 3D vector for spatial calculations
|
|
3
|
+
* HoloScript v3.2 - Autonomous Agent Swarms
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 3D Vector class for spatial operations
|
|
8
|
+
*/
|
|
9
|
+
export class Vector3 {
|
|
10
|
+
constructor(
|
|
11
|
+
public x: number = 0,
|
|
12
|
+
public y: number = 0,
|
|
13
|
+
public z: number = 0
|
|
14
|
+
) {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create from array
|
|
18
|
+
*/
|
|
19
|
+
static fromArray(arr: number[]): Vector3 {
|
|
20
|
+
return new Vector3(arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create zero vector
|
|
25
|
+
*/
|
|
26
|
+
static zero(): Vector3 {
|
|
27
|
+
return new Vector3(0, 0, 0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create unit vector
|
|
32
|
+
*/
|
|
33
|
+
static one(): Vector3 {
|
|
34
|
+
return new Vector3(1, 1, 1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Add another vector
|
|
39
|
+
*/
|
|
40
|
+
add(v: Vector3): Vector3 {
|
|
41
|
+
return new Vector3(this.x + v.x, this.y + v.y, this.z + v.z);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Subtract another vector
|
|
46
|
+
*/
|
|
47
|
+
subtract(v: Vector3): Vector3 {
|
|
48
|
+
return new Vector3(this.x - v.x, this.y - v.y, this.z - v.z);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Multiply by scalar
|
|
53
|
+
*/
|
|
54
|
+
multiply(scalar: number): Vector3 {
|
|
55
|
+
return new Vector3(this.x * scalar, this.y * scalar, this.z * scalar);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Divide by scalar
|
|
60
|
+
*/
|
|
61
|
+
divide(scalar: number): Vector3 {
|
|
62
|
+
if (scalar === 0) return Vector3.zero();
|
|
63
|
+
return new Vector3(this.x / scalar, this.y / scalar, this.z / scalar);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get magnitude (length)
|
|
68
|
+
*/
|
|
69
|
+
magnitude(): number {
|
|
70
|
+
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get squared magnitude (faster for comparisons)
|
|
75
|
+
*/
|
|
76
|
+
magnitudeSquared(): number {
|
|
77
|
+
return this.x * this.x + this.y * this.y + this.z * this.z;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Normalize to unit vector
|
|
82
|
+
*/
|
|
83
|
+
normalize(): Vector3 {
|
|
84
|
+
const mag = this.magnitude();
|
|
85
|
+
if (mag === 0) return Vector3.zero();
|
|
86
|
+
return this.divide(mag);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Dot product
|
|
91
|
+
*/
|
|
92
|
+
dot(v: Vector3): number {
|
|
93
|
+
return this.x * v.x + this.y * v.y + this.z * v.z;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Cross product
|
|
98
|
+
*/
|
|
99
|
+
cross(v: Vector3): Vector3 {
|
|
100
|
+
return new Vector3(
|
|
101
|
+
this.y * v.z - this.z * v.y,
|
|
102
|
+
this.z * v.x - this.x * v.z,
|
|
103
|
+
this.x * v.y - this.y * v.x
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Distance to another vector
|
|
109
|
+
*/
|
|
110
|
+
distanceTo(v: Vector3): number {
|
|
111
|
+
return this.subtract(v).magnitude();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Squared distance (faster for comparisons)
|
|
116
|
+
*/
|
|
117
|
+
distanceToSquared(v: Vector3): number {
|
|
118
|
+
return this.subtract(v).magnitudeSquared();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Linear interpolation
|
|
123
|
+
*/
|
|
124
|
+
lerp(v: Vector3, t: number): Vector3 {
|
|
125
|
+
return this.add(v.subtract(this).multiply(t));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Clamp magnitude
|
|
130
|
+
*/
|
|
131
|
+
clampMagnitude(maxLength: number): Vector3 {
|
|
132
|
+
const mag = this.magnitude();
|
|
133
|
+
if (mag > maxLength && mag > 0) {
|
|
134
|
+
return this.divide(mag).multiply(maxLength);
|
|
135
|
+
}
|
|
136
|
+
return new Vector3(this.x, this.y, this.z);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Check equality within epsilon
|
|
141
|
+
*/
|
|
142
|
+
equals(v: Vector3, epsilon = 0.0001): boolean {
|
|
143
|
+
return (
|
|
144
|
+
Math.abs(this.x - v.x) < epsilon &&
|
|
145
|
+
Math.abs(this.y - v.y) < epsilon &&
|
|
146
|
+
Math.abs(this.z - v.z) < epsilon
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Clone vector
|
|
152
|
+
*/
|
|
153
|
+
clone(): Vector3 {
|
|
154
|
+
return new Vector3(this.x, this.y, this.z);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Convert to array
|
|
159
|
+
*/
|
|
160
|
+
toArray(): [number, number, number] {
|
|
161
|
+
return [this.x, this.y, this.z];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* String representation
|
|
166
|
+
*/
|
|
167
|
+
toString(): string {
|
|
168
|
+
return `Vector3(${this.x.toFixed(3)}, ${this.y.toFixed(3)}, ${this.z.toFixed(3)})`;
|
|
169
|
+
}
|
|
170
|
+
}
|