diff --git a/src/NwcIO/Model/Sectioning/NwcXmlViewpointSerializer.cs b/src/NwcIO/Model/Sectioning/NwcXmlViewpointSerializer.cs index 0b68d04..adc0b66 100644 --- a/src/NwcIO/Model/Sectioning/NwcXmlViewpointSerializer.cs +++ b/src/NwcIO/Model/Sectioning/NwcXmlViewpointSerializer.cs @@ -99,17 +99,12 @@ private static XElement SerializeViewpoint(NwcSavedViewpoint vp) new XAttribute("guid", vp.Id.ToString()), camElem); - // Section planes - var allPlanes = new List(vp.SectionPlanes); - if (vp.SectionBox is not null && vp.SectionBox.IsEnabled) - { - allPlanes.AddRange(vp.SectionBox.ToSectionPlanes()); - } - - if (allPlanes.Count > 0) + // Section planes: only the viewpoint's own. The section box is written once, as below; its + // planes here would be read back as section planes, adding six more on every round trip. + if (vp.SectionPlanes.Count > 0) { var planesElem = new XElement("clip_planes"); - foreach (var plane in allPlanes) + foreach (var plane in vp.SectionPlanes) { planesElem.Add(new XElement("clip_plane", new XAttribute("index", plane.PlaneIndex), diff --git a/tests/NwcIO.Tests/XmlViewpointSerializerTests.cs b/tests/NwcIO.Tests/XmlViewpointSerializerTests.cs index 505c69d..024c81e 100644 --- a/tests/NwcIO.Tests/XmlViewpointSerializerTests.cs +++ b/tests/NwcIO.Tests/XmlViewpointSerializerTests.cs @@ -86,6 +86,38 @@ public void Serialize_Roundtrip_PreservesViewpointDetails() Assert.Equal(12.0, rArrow.EndPoint.X, 3); } + [Fact] + public void Serialize_SectionBoxAndPlane_RoundTripsUnchanged() + { + var bounds = new BoundingBox3d(new Vector3d(0, 0, 0), new Vector3d(1, 2, 3)); + var top = NwcSectionPlane.CreateTop(4.5, 7); + var list = new List + { + new() + { + Name = "v", + Camera = new NwcCamera(), + SectionPlanes = [top], + SectionBox = new NwcSectionBox(bounds, true), + }, + }; + + for (int round = 0; round < 3; round++) + { + list = NwcXmlViewpointSerializer.Deserialize(NwcXmlViewpointSerializer.Serialize(list)).ToList(); + + var vp = Assert.Single(list); + var plane = Assert.Single(vp.SectionPlanes); + Assert.Equal(7, plane.PlaneIndex); + Assert.Equal(top.Normal, plane.Normal); + Assert.Equal(top.Distance, plane.Distance); + Assert.Equal(NwcSectionAlignment.Top, plane.Alignment); + Assert.NotNull(vp.SectionBox); + Assert.True(vp.SectionBox.IsEnabled); + Assert.Equal(bounds, vp.SectionBox.Bounds); + } + } + [Fact] public void Serialize_EmptyList_ReturnsValidRootElement() {