From 9adf9b5bafea2afe52d018d93a370ab2c65e63f2 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Thu, 19 Mar 2026 23:12:49 +0800 Subject: [PATCH] Fix assembly reference rod and start-point path creation --- resources/unit_cylinder.nwc | Bin 1980 -> 2299 bytes resources/unit_cylinder.obj | 201 ++++++++++++------ src/UI/WPF/ViewModels/PathEditingViewModel.cs | 68 ++++-- src/UI/WPF/Views/PathEditingView.xaml | 30 +++ 4 files changed, 221 insertions(+), 78 deletions(-) diff --git a/resources/unit_cylinder.nwc b/resources/unit_cylinder.nwc index 540b4e6bcbcc8d9b3037500d27ab9fdabeaf179e..8fbca10ff7c38ea5d4e270902439dd0513b7584c 100644 GIT binary patch delta 1406 zcmV-^1%dj!5Bm|2IDfH913?gmFIp&)LhY=4f*c5`u1y=F#ict~#=TKi=XRHwTf^ZC zq|7V$1i@19bt1lnPI5^l_`|omEdR{^pJct}%A}~~f-F^uL=9FDqf|3^ak2>fEG2`N z7`PoVI2tt}`Bu*wrDBwj*y<~J*BaZA^EGlF?w@q;k7|AX>3_C4uV;PUl`^%ng`Eaa z=N+X-=L@n__cMb7gZ{oylA!4fh|xM!n-ul$c<(#tNV!(Fy(o{!4}lx-7IV^|+y)|u zg4wBhYGtepmCb7TwOno1AK&k9m%DDaFxi{SE@E+$W%)mQ8KFfJfuX^coi&kNBY*q- z0y`>bb^tBIVv{rhDt~>{Plysx7y$4W%@hQM&>lkZ;z6QI5O{EiH>R_*uxy~j1PfUb zyA_CO`)}6GH3v7rLx|+1o9j^z9-@na(?vXZsE!_z31x2mxdkHF`^I^@55XRM&Trm) z^Ue3>4Q?TX9+TK6ahJq%67P{U^q=xyeC>qm5Q}yo=4koH$A9k_p&aDsj75|Cgh^QQ zjLE$@O!BOG#v*wRCeO3x8PjL!c2Glphsp1p=jS?1eQM~Z!}LQf&aa>KPc1?{d+j=7 zaiI@tnva=$%+$wBea!TOnSLS=-w!`{xcTVG)9n}Wm#_BJqhljrgbaDp zSVP8|AsefPM9zc8JtOcYdz^WFls;4s_V;#opw=@ITO>ZrX0tn1^@JngaA?00hhpFW z&iOCzKAQ=59NcRA>Wye$0V}mpMV6`pI8quG{9e@so`2?@TA5Eyz)o$NFOGWy@URdm z#k#FFcvMkpzPeHa`|7Rss1hlGW8L0hSeWL)#c^`t)SMc)%&V?xepmqey;UJn8dbou z)K{PqxDj>7TkTjE+)R1Wy+Lsd<}zkBIVtmCGs|UEm){Haq?@U#AWL9(99Gqcg8Par zx#P_gxLzvwy`D6e0jsVuZ)VNxd=EB$6KP1h{dLLswrtGrzfR(^eGKQWUb^x&czPPX zv9dxyrf!~)A0dZUFDwb}KiA+-=O6HNcdB@tV`N}pU<6_}CI*HM76t|Y1eO5TvwQ+5 z0Y*6BF8lkEeUT8<@@zdg|S+a8BB6nwCU(NzrHe|{;xv_}zoe@{!pFcbjr=>A-W3{i)m-gg#{o~&*PV;ids5f6*)+Zt?} znr4ihcK7Dj(X(H{k7G@iS4ZP?fk&WyzrMWJWLcKg2_ZEV9j}*MUO3bXfNT-7&T#)C z#dV^>)0q!ib!UDXcmz_+9UdhD(p0@KsW`QtrMMK4*?c9J0 z@VnfHRFk)o$*)=U8n)|GA(>=6HuXNxy;`nNkN%*(;K{Pyux#?`WOdHky7_eYgn2Z) zW+15Wg1k>a|GeqEEkP#{#4+ETwsZfEeq?#w2Uc#e5N_fzFVsD% zn%%eDE;@B>BObfz01-`bMtUu(>-*h7cQ=6XEqx3D%?sw+_vjnR)RRfU&%^1I6Iyp0 M2LJ#70001xG&%sXPXGV_ delta 1083 zcmV-B1jPIM5xftOIDaut12GUqHy{KB4RlnTAeNA*woMxaicQ5z*5DnGVb->0)-k_|mg2>(BguSPYsgld_%*veXq4wOB(+QqSPY%OdilR185< z`7*XI)P|G{`32KIqDd-+$!D!H{>ROx~U|@&?;#45E0b(y8_5)(B>x-?qt}9!wdDOcb$li^_2GJln zusAXsB*y^Pi(o_5SR<*oMl#EV6+11&V(a8xrN=;=*PKb>P4}S^t^ZmfUP+Z9n7!nzm zoRM2pUgPf_;14k)4Tw{Kc-#N~|9OCPV-!fVe(Ak?i>en@gV;)njZuwJN{S#hNbKId z`lSqDl}d_nEpaU%Hb@Ml2gC-60aZ6)gBOs&MPvY!1p^TvW`WW!KoA=0>cYSf5*h*I z8#FMuGD0y!Fdz#Gj~OTr00oKI0(hKbWME)m1Y&L=k-)^j0006J0CBUr11JGWNN`sF zZEpZ%umCZW0uVzbQi0eUh#7%64T#Oaq7C-gF?O)#s5;09hIAl~1!Au2i+3YoYZ%6* zU)t)XeYMa(FGeUI0R2!JQj;hJnOf9;dq3VWYoa|4X(;$$52LFXy8rxAd})s=uHrzP zeoXtA&{Q&^h<(6t7aJN)9KbXO3L22**{N(EGnLIl4=YN|W1+HntW-7+Q$0FOtUaXa z!!!o~*0n7uvl|9X0e{a*!!Q^C@XXCql_CCN2fYb;^xzZNxhafwSd|?-7~5}aux)CZ zG6o*JdG_Yx`2xOyP?Pnmqp`X`2(;g?-=8MW^Sn(6vD6-TPSQQIsTTlgkYb(U`9-Sh zKy6P)-f1jPk65MOKrjFGb|!@C^_IcxJOtf#>0i*_8(#N;nR_gR%Xq>oc|XwkhTB4? zu5H9)R}~P^6lbJYcfG#fO?2Zcm|W9`5YRXnZ{DMCA<>d2&6t#MU68LT;02Sx2s$@K B{*V9w diff --git a/resources/unit_cylinder.obj b/resources/unit_cylinder.obj index f920599..3b4e1ca 100644 --- a/resources/unit_cylinder.obj +++ b/resources/unit_cylinder.obj @@ -1,58 +1,104 @@ # unit cylinder for assembly reference rod -# dimensions: length 0.01m along +X, diameter 0.01m +# dimensions: length 1.0 along +X, diameter 1.0 # centered at origin +# when Navisworks imports OBJ as centimeters, generated NWC becomes 0.01m base size o unit_cylinder -v -0.005000 0.000000 0.000000 -v -0.005000 0.005000 0.000000 -v -0.005000 0.004330 0.002500 -v -0.005000 0.002500 0.004330 -v -0.005000 0.000000 0.005000 -v -0.005000 -0.002500 0.004330 -v -0.005000 -0.004330 0.002500 -v -0.005000 -0.005000 0.000000 -v -0.005000 -0.004330 -0.002500 -v -0.005000 -0.002500 -0.004330 -v -0.005000 0.000000 -0.005000 -v -0.005000 0.002500 -0.004330 -v -0.005000 0.004330 -0.002500 -v 0.005000 0.000000 0.000000 -v 0.005000 0.005000 0.000000 -v 0.005000 0.004330 0.002500 -v 0.005000 0.002500 0.004330 -v 0.005000 0.000000 0.005000 -v 0.005000 -0.002500 0.004330 -v 0.005000 -0.004330 0.002500 -v 0.005000 -0.005000 0.000000 -v 0.005000 -0.004330 -0.002500 -v 0.005000 -0.002500 -0.004330 -v 0.005000 0.000000 -0.005000 -v 0.005000 0.002500 -0.004330 -v 0.005000 0.004330 -0.002500 -f 2 15 16 -f 2 16 3 -f 3 16 17 -f 3 17 4 -f 4 17 18 -f 4 18 5 -f 5 18 19 -f 5 19 6 -f 6 19 20 -f 6 20 7 -f 7 20 21 -f 7 21 8 -f 8 21 22 -f 8 22 9 -f 9 22 23 -f 9 23 10 -f 10 23 24 -f 10 24 11 -f 11 24 25 -f 11 25 12 -f 12 25 26 -f 12 26 13 -f 13 26 15 -f 13 15 2 -f 1 3 2 +v -0.500000 0.000000 0.000000 +v 0.500000 0.000000 0.000000 +v -0.500000 0.500000 0.000000 +v -0.500000 0.482963 0.129410 +v -0.500000 0.433013 0.250000 +v -0.500000 0.353553 0.353553 +v -0.500000 0.250000 0.433013 +v -0.500000 0.129410 0.482963 +v -0.500000 0.000000 0.500000 +v -0.500000 -0.129410 0.482963 +v -0.500000 -0.250000 0.433013 +v -0.500000 -0.353553 0.353553 +v -0.500000 -0.433013 0.250000 +v -0.500000 -0.482963 0.129410 +v -0.500000 -0.500000 0.000000 +v -0.500000 -0.482963 -0.129410 +v -0.500000 -0.433013 -0.250000 +v -0.500000 -0.353553 -0.353553 +v -0.500000 -0.250000 -0.433013 +v -0.500000 -0.129410 -0.482963 +v -0.500000 0.000000 -0.500000 +v -0.500000 0.129410 -0.482963 +v -0.500000 0.250000 -0.433013 +v -0.500000 0.353553 -0.353553 +v -0.500000 0.433013 -0.250000 +v -0.500000 0.482963 -0.129410 +v 0.500000 0.500000 0.000000 +v 0.500000 0.482963 0.129410 +v 0.500000 0.433013 0.250000 +v 0.500000 0.353553 0.353553 +v 0.500000 0.250000 0.433013 +v 0.500000 0.129410 0.482963 +v 0.500000 0.000000 0.500000 +v 0.500000 -0.129410 0.482963 +v 0.500000 -0.250000 0.433013 +v 0.500000 -0.353553 0.353553 +v 0.500000 -0.433013 0.250000 +v 0.500000 -0.482963 0.129410 +v 0.500000 -0.500000 0.000000 +v 0.500000 -0.482963 -0.129410 +v 0.500000 -0.433013 -0.250000 +v 0.500000 -0.353553 -0.353553 +v 0.500000 -0.250000 -0.433013 +v 0.500000 -0.129410 -0.482963 +v 0.500000 0.000000 -0.500000 +v 0.500000 0.129410 -0.482963 +v 0.500000 0.250000 -0.433013 +v 0.500000 0.353553 -0.353553 +v 0.500000 0.433013 -0.250000 +v 0.500000 0.482963 -0.129410 +f 3 26 27 +f 3 27 4 +f 4 27 28 +f 4 28 5 +f 5 28 29 +f 5 29 6 +f 6 29 30 +f 6 30 7 +f 7 30 31 +f 7 31 8 +f 8 31 32 +f 8 32 9 +f 9 32 33 +f 9 33 10 +f 10 33 34 +f 10 34 11 +f 11 34 35 +f 11 35 12 +f 12 35 36 +f 12 36 13 +f 13 36 37 +f 13 37 14 +f 14 37 38 +f 14 38 15 +f 15 38 39 +f 15 39 16 +f 16 39 40 +f 16 40 17 +f 17 40 41 +f 17 41 18 +f 18 41 42 +f 18 42 19 +f 19 42 43 +f 19 43 20 +f 20 43 44 +f 20 44 21 +f 21 44 45 +f 21 45 22 +f 22 45 46 +f 22 46 23 +f 23 46 47 +f 23 47 24 +f 24 47 48 +f 24 48 25 +f 25 48 49 +f 25 49 26 f 1 4 3 f 1 5 4 f 1 6 5 @@ -63,16 +109,41 @@ f 1 10 9 f 1 11 10 f 1 12 11 f 1 13 12 -f 1 2 13 -f 14 15 16 -f 14 16 17 -f 14 17 18 -f 14 18 19 -f 14 19 20 -f 14 20 21 -f 14 21 22 -f 14 22 23 -f 14 23 24 -f 14 24 25 -f 14 25 26 -f 14 26 15 +f 1 14 13 +f 1 15 14 +f 1 16 15 +f 1 17 16 +f 1 18 17 +f 1 19 18 +f 1 20 19 +f 1 21 20 +f 1 22 21 +f 1 23 22 +f 1 24 23 +f 1 25 24 +f 1 26 25 +f 1 3 26 +f 2 27 28 +f 2 28 29 +f 2 29 30 +f 2 30 31 +f 2 31 32 +f 2 32 33 +f 2 33 34 +f 2 34 35 +f 2 35 36 +f 2 36 37 +f 2 37 38 +f 2 38 39 +f 2 39 40 +f 2 40 41 +f 2 41 42 +f 2 42 43 +f 2 43 44 +f 2 44 45 +f 2 45 46 +f 2 46 47 +f 2 47 48 +f 2 48 49 +f 2 49 26 +f 2 26 27 diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs index 37eb74a..240c311 100644 --- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs +++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs @@ -122,10 +122,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels private ObservableCollection> _railPayloadAnchorModeOptions; private const double DefaultAssemblyReferenceRodLengthInMeters = 20.0; private static readonly double DefaultAssemblyReferenceRodDiameterInMeters = CalculateDefaultAssemblyReferenceRodDiameterInMeters(); + private const double DefaultAssemblyAnchorVerticalOffsetInMeters = 0.0; private string _assemblyTerminalObjectName = "未选择"; private string _assemblyTerminalObjectInfo = "请选择终点处已安装箱体"; private double _assemblyReferenceRodLengthInMeters = DefaultAssemblyReferenceRodLengthInMeters; private double _assemblyReferenceRodDiameterInMeters = DefaultAssemblyReferenceRodDiameterInMeters; + private double _assemblyAnchorVerticalOffsetInMeters = DefaultAssemblyAnchorVerticalOffsetInMeters; private string _assemblyStartPointText = "未选择"; private RailMountMode _assemblyMountMode = RailMountMode.UnderRail; private RailPayloadAnchorMode _assemblyPayloadAnchorMode = RailPayloadAnchorMode.TopCenter; @@ -374,6 +376,20 @@ namespace NavisworksTransport.UI.WPF.ViewModels } } + public double AssemblyAnchorVerticalOffsetInMeters + { + get => _assemblyAnchorVerticalOffsetInMeters; + set + { + if (SetProperty(ref _assemblyAnchorVerticalOffsetInMeters, value) && HasAssemblyTerminalObject) + { + RefreshAssemblyTerminalObjectInfo(); + RenderAssemblyAnchorMarker(); + RefreshAssemblyReferenceRodIfNeeded(); + } + } + } + public bool HasAssemblyTerminalObject { get => _hasAssemblyTerminalObject; @@ -1304,6 +1320,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels HasAssemblyTerminalObject = true; AssemblyStartPointText = "未选择"; AssemblyTerminalObjectName = ModelItemAnalysisHelper.GetSafeDisplayName(selectedItem); + InitializeAssemblyAnchorVerticalOffsetFromTerminalObject(); RefreshAssemblyTerminalObjectInfo(); RenderAssemblyAnchorMarker(); OnPropertyChanged(nameof(CanGenerateAssemblyReferenceRod)); @@ -1420,6 +1437,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels Point3D projectedStartPoint = AssemblyReferencePathManager.Instance.ProjectPointToReferenceLine(pickResult.Point); _assemblyStartPoint = projectedStartPoint; AssemblyStartPointText = $"({projectedStartPoint.X:F2}, {projectedStartPoint.Y:F2}, {projectedStartPoint.Z:F2})"; + LogManager.Info( + $"[直线装配] 点击点=({pickResult.Point.X:F2}, {pickResult.Point.Y:F2}, {pickResult.Point.Z:F2})," + + $"投影起点=({projectedStartPoint.X:F2}, {projectedStartPoint.Y:F2}, {projectedStartPoint.Z:F2})"); await SafeExecuteAsync(() => { @@ -1450,7 +1470,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels RailPathDefinitionMode = RailPathDefinitionMode.RailCenterLine }; - route.AddPoint(new PathPoint(_assemblyStartPoint, "装配起点", PathPointType.StartPoint)); + route.AddPoint(new PathPoint(startPoint, "装配起点", PathPointType.StartPoint)); route.AddPoint(new PathPoint(endPoint, "装配终点", PathPointType.EndPoint)); if (!_pathPlanningManager.AddRoute(route)) @@ -1459,14 +1479,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels } _pathPlanningManager.SetCurrentRoute(route); - _pathPlanningManager.DrawRouteVisualization(route, isAutoPath: false); - _pathPlanningManager.SavePathToDatabase(route); - if (!_pathPlanningManager.GeneratePath(route)) { throw new InvalidOperationException("装配路径生成失败"); } + _pathPlanningManager.DrawRouteVisualization(route, isAutoPath: false); + RefreshPathRoutes(); + + var generatedRouteViewModel = PathRoutes.FirstOrDefault(p => p.Name == route.Name); + if (generatedRouteViewModel != null) + { + SelectedPathRoute = generatedRouteViewModel; + UpdatePassageSpaceVisualizationForPathType(route.PathType); + } + AssemblyTerminalObjectInfo = string.Format( "对接终点=({0:F2}, {1:F2}, {2:F2}),装配起点={3},安装方式={4},对接基准={5}", endPoint.X, @@ -1477,7 +1504,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels AssemblyPayloadAnchorMode == RailPayloadAnchorMode.TopCenter ? "顶面对接" : "底面对接"); OnPropertyChanged(nameof(PathRoutes)); - LogManager.Info($"[直线装配] 已生成路径: {route.Name}"); + LogManager.Info($"[直线装配] 已生成路径: {route.Name},起点=({startPoint.X:F2}, {startPoint.Y:F2}, {startPoint.Z:F2}),终点=({endPoint.X:F2}, {endPoint.Y:F2}, {endPoint.Z:F2})"); } private Point3D GetAssemblyTerminalAnchorPoint() @@ -1490,14 +1517,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels var bounds = _assemblyTerminalObject.BoundingBox(); var center = bounds.Center; Vector3D up = ModelItemTransformHelper.GetUpDirectionFromTransform(_assemblyTerminalObject.Transform); - Vector3D localSize = ModelItemTransformHelper.EstimateLocalBoxSize(bounds, _assemblyTerminalObject.Transform); - double halfHeight = Math.Max(0.0, localSize.Z / 2.0); double direction = AssemblyPayloadAnchorMode == RailPayloadAnchorMode.TopCenter ? 1.0 : -1.0; + double verticalOffset = UnitsConverter.ConvertFromMeters(AssemblyAnchorVerticalOffsetInMeters); return new Point3D( - center.X + up.X * halfHeight * direction, - center.Y + up.Y * halfHeight * direction, - center.Z + up.Z * halfHeight * direction); + center.X + up.X * verticalOffset * direction, + center.Y + up.Y * verticalOffset * direction, + center.Z + up.Z * verticalOffset * direction); } private AssemblyReferenceLine BuildAssemblyReferenceLine() @@ -1548,7 +1574,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (referenceStartPoint != null && referenceEndPoint != null) { AssemblyTerminalObjectInfo = string.Format( - "中心=({0:F2}, {1:F2}, {2:F2}),尺寸=({3:F2}, {4:F2}, {5:F2}),{6},{7}点=({8:F2}, {9:F2}, {10:F2}),参考杆起点=({11:F2}, {12:F2}, {13:F2})", + "中心=({0:F2}, {1:F2}, {2:F2}),尺寸=({3:F2}, {4:F2}, {5:F2}),{6},{7}点=({8:F2}, {9:F2}, {10:F2}),垂直偏移={11:F3}m,参考杆起点=({12:F2}, {13:F2}, {14:F2})", bounds.Center.X, bounds.Center.Y, bounds.Center.Z, @@ -1560,6 +1586,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels referenceEndPoint.X, referenceEndPoint.Y, referenceEndPoint.Z, + AssemblyAnchorVerticalOffsetInMeters, referenceStartPoint.X, referenceStartPoint.Y, referenceStartPoint.Z); @@ -1567,7 +1594,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels } AssemblyTerminalObjectInfo = string.Format( - "中心=({0:F2}, {1:F2}, {2:F2}),尺寸=({3:F2}, {4:F2}, {5:F2}),{6},{7}点=({8:F2}, {9:F2}, {10:F2})", + "中心=({0:F2}, {1:F2}, {2:F2}),尺寸=({3:F2}, {4:F2}, {5:F2}),{6},{7}点=({8:F2}, {9:F2}, {10:F2}),垂直偏移={11:F3}m", bounds.Center.X, bounds.Center.Y, bounds.Center.Z, @@ -1578,7 +1605,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels anchorText, anchorPoint.X, anchorPoint.Y, - anchorPoint.Z); + anchorPoint.Z, + AssemblyAnchorVerticalOffsetInMeters); } private void RefreshAssemblyReferenceRodIfNeeded() @@ -1609,6 +1637,20 @@ namespace NavisworksTransport.UI.WPF.ViewModels } } + private void InitializeAssemblyAnchorVerticalOffsetFromTerminalObject() + { + if (_assemblyTerminalObject == null || !ModelItemAnalysisHelper.IsModelItemValid(_assemblyTerminalObject)) + { + return; + } + + var bounds = _assemblyTerminalObject.BoundingBox(); + Vector3D localSize = ModelItemTransformHelper.EstimateLocalBoxSize(bounds, _assemblyTerminalObject.Transform); + double suggestedOffset = UnitsConverter.ConvertToMeters(Math.Max(0.0, localSize.Z / 2.0)); + _assemblyAnchorVerticalOffsetInMeters = suggestedOffset; + OnPropertyChanged(nameof(AssemblyAnchorVerticalOffsetInMeters)); + } + private sealed class AssemblyReferenceLine { public AssemblyReferenceLine(Point3D startPoint, Point3D endPoint, Vector3D direction) diff --git a/src/UI/WPF/Views/PathEditingView.xaml b/src/UI/WPF/Views/PathEditingView.xaml index e8f87cb..e493651 100644 --- a/src/UI/WPF/Views/PathEditingView.xaml +++ b/src/UI/WPF/Views/PathEditingView.xaml @@ -332,6 +332,7 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管 +