diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs index 55c17f9..c7c290f 100644 --- a/src/Core/Animation/PathAnimationManager.cs +++ b/src/Core/Animation/PathAnimationManager.cs @@ -86,6 +86,8 @@ namespace NavisworksTransport.Core.Animation { private static PathAnimationManager _instance; private static readonly HashSet _completedCollisionTests = new HashSet(); // 记录已完成碰撞检测的动画配置 + private static readonly Dictionary> _animationFrameCache = new Dictionary>(); // 动画帧缓存 + private static readonly Dictionary> _collisionResultCache = new Dictionary>(); // 碰撞结果缓存 private ModelItem _animatedObject; private List _pathPoints; private List _manualCollisionTargets = new List(); @@ -328,7 +330,43 @@ namespace NavisworksTransport.Core.Animation LogManager.Info($"使用路径,边数:{route.Edges.Count},总长度:{route.TotalLength:F2}米,动画时长:{durationSeconds:F1}秒"); - PrecomputeAnimationFrames(); + // 计算动画配置哈希(基于路径边,可以区分不同的曲线化路径) + _currentAnimationHash = ComputeAnimationConfigHashFromRoute(animatedObject, route); + LogManager.Info($"动画配置哈希: {_currentAnimationHash}"); + + // 检查动画帧缓存 + if (_animationFrameCache.TryGetValue(_currentAnimationHash, out var cachedFrames)) + { + _animationFrames = cachedFrames; + // 同时加载缓存的碰撞结果 + if (_collisionResultCache.TryGetValue(_currentAnimationHash, out var cachedCollisions)) + { + _allCollisionResults = cachedCollisions; + LogManager.Info($"使用缓存的动画帧和碰撞结果,帧数: {_animationFrames.Count}, 碰撞数: {_allCollisionResults.Count}"); + } + else + { + _allCollisionResults = new List(); + LogManager.Info($"使用缓存的动画帧,但碰撞结果缓存缺失,帧数: {_animationFrames.Count}"); + } + } + else + { + // 缓存未命中,重新计算动画帧 + LogManager.Info("缓存未命中,重新计算动画帧和碰撞结果"); + PrecomputeAnimationFrames(); + + // 缓存动画帧和碰撞结果 + if (_animationFrames != null && _animationFrames.Count > 0) + { + _animationFrameCache[_currentAnimationHash] = _animationFrames; + if (_allCollisionResults != null) + { + _collisionResultCache[_currentAnimationHash] = _allCollisionResults; + } + LogManager.Info($"动画帧和碰撞结果已缓存,帧数: {_animationFrames.Count}, 碰撞数: {_allCollisionResults?.Count ?? 0}"); + } + } // 验证预计算结果 if (_animationFrames == null || _animationFrames.Count == 0) @@ -705,19 +743,19 @@ namespace NavisworksTransport.Core.Animation // 在第一帧打印完整信息(使用静态变量确保每个圆弧段只打印一次) if (!_arcInfoPrinted.Contains(currentEdgeIndex)) { - LogManager.Info($"圆弧段[{currentEdgeIndex}]朝向信息:"); - LogManager.Info($" 前直线段朝向: {prevStraightYaw * 180.0 / Math.PI:F2}度"); - LogManager.Info($" 进入切点(Ts)朝向: {tsYaw * 180.0 / Math.PI:F2}度"); - LogManager.Info($" 圆弧偏转角度: {signedAngle * 180.0 / Math.PI:F2}度"); - LogManager.Info($" 退出切点(Te)朝向: {teYaw * 180.0 / Math.PI:F2}度"); - LogManager.Info($" 后直线段朝向: {nextStraightYaw * 180.0 / Math.PI:F2}度"); - LogManager.Info($" 前后直线段朝向差: {(nextStraightYaw - prevStraightYaw) * 180.0 / Math.PI:F2}度"); - LogManager.Info($" 圆弧段朝向变化: {yawChange * 180.0 / Math.PI:F2}度"); + LogManager.Debug($"圆弧段[{currentEdgeIndex}]朝向信息:"); + LogManager.Debug($" 前直线段朝向: {prevStraightYaw * 180.0 / Math.PI:F2}度"); + LogManager.Debug($" 进入切点(Ts)朝向: {tsYaw * 180.0 / Math.PI:F2}度"); + LogManager.Debug($" 圆弧偏转角度: {signedAngle * 180.0 / Math.PI:F2}度"); + LogManager.Debug($" 退出切点(Te)朝向: {teYaw * 180.0 / Math.PI:F2}度"); + LogManager.Debug($" 后直线段朝向: {nextStraightYaw * 180.0 / Math.PI:F2}度"); + LogManager.Debug($" 前后直线段朝向差: {(nextStraightYaw - prevStraightYaw) * 180.0 / Math.PI:F2}度"); + LogManager.Debug($" 圆弧段朝向变化: {yawChange * 180.0 / Math.PI:F2}度"); _arcInfoPrinted.Add(currentEdgeIndex); } // 每一帧都打印当前朝向 - LogManager.Info($"帧[{frameIndex}] 圆弧段[{currentEdgeIndex}]: 进度={edgeProgress:F4}, 当前朝向={currentYaw * 180.0 / Math.PI:F2}度"); + LogManager.Debug($"帧[{frameIndex}] 圆弧段[{currentEdgeIndex}]: 进度={edgeProgress:F4}, 当前朝向={currentYaw * 180.0 / Math.PI:F2}度"); return currentYaw; } @@ -2467,6 +2505,65 @@ namespace NavisworksTransport.Core.Animation } } + /// + /// 计算动画配置的哈希值(基于PathRoute的Edges,可以区分不同的曲线化路径) + /// + private string ComputeAnimationConfigHashFromRoute(ModelItem animatedObject, PathRoute route) + { + try + { + var sb = new StringBuilder(); + + // 包含对象名称 + sb.Append(animatedObject?.DisplayName ?? "null"); + sb.Append("|"); + + // 包含路径ID(区分不同的路径) + sb.Append(route?.Id ?? "null"); + sb.Append("|"); + + // 包含动画参数(确保参数改变时重新检测) + sb.Append($"Duration:{_animationDuration:F2}s"); + sb.Append($"|FrameRate:{_animationFrameRate}"); + sb.Append($"|DetectionGap:{_detectionGap:F4}"); + sb.Append("|"); + + // 包含虚拟车辆尺寸(确保车辆尺寸改变时重新检测) + var vehicleConfig = ConfigManager.Instance.Current.PathEditing; + sb.Append($"Vehicle:{vehicleConfig.VehicleLengthMeters:F2}x{vehicleConfig.VehicleWidthMeters:F2}x{vehicleConfig.VehicleHeightMeters:F2}"); + sb.Append("|"); + + // 包含路径边的摘要信息(区分不同的曲线化结果) + if (route?.Edges != null) + { + foreach (var edge in route.Edges) + { + sb.Append(edge.SegmentType.ToString()); + sb.Append($"({edge.PhysicalLength:F2})"); + if (edge.SegmentType == PathSegmentType.Arc && edge.Trajectory != null) + { + sb.Append($"_R{edge.Trajectory.ActualRadius:F2}"); + sb.Append($"_A{edge.Trajectory.DeflectionAngle:F2}"); + } + sb.Append(";"); + } + } + + // 计算哈希 + using (var md5 = System.Security.Cryptography.MD5.Create()) + { + var inputBytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString()); + var hashBytes = md5.ComputeHash(inputBytes); + return BitConverter.ToString(hashBytes).Replace("-", ""); + } + } + catch (Exception ex) + { + LogManager.Warning($"计算动画配置哈希失败: {ex.Message}"); + return DateTime.Now.Ticks.ToString(); // 回退到时间戳 + } + } + /// /// 强制重新创建碰撞测试(清除指定配置的碰撞检测记录) ///