diff --git a/Xbim.Geometry.Engine.Interop.Tests/Ifc4GeometryTests.cs b/Xbim.Geometry.Engine.Interop.Tests/Ifc4GeometryTests.cs index 7a2193561..e3062a7d2 100644 --- a/Xbim.Geometry.Engine.Interop.Tests/Ifc4GeometryTests.cs +++ b/Xbim.Geometry.Engine.Interop.Tests/Ifc4GeometryTests.cs @@ -202,7 +202,7 @@ public void CsgSolidBoundingBoxTest() { Assert.IsTrue(er.Entity != null, "No IfcCsgSolid found"); var solid = geomEngine.CreateSolidSet(er.Entity, logger).FirstOrDefault(); - Assert.IsTrue(Math.Abs(solid.Volume - solid.BoundingBox.Volume) < 1e-5); + Assert.IsTrue(Math.Abs((solid.Volume - solid.BoundingBox.Volume) ?? double.NaN) < 1e-5); } } @@ -215,7 +215,7 @@ public void ExtrudedAreaSolidBasicTest() var eas = model.Instances.OfType().FirstOrDefault(); Assert.IsNotNull(eas); var solid = geomEngine.CreateSolid(eas); - Assert.IsTrue(Math.Abs(solid.Volume - solid.BoundingBox.Volume) < 1e-5); + Assert.IsTrue(Math.Abs((solid.Volume - solid.BoundingBox.Volume) ?? double.NaN) < 1e-5); } } [TestMethod] @@ -270,7 +270,7 @@ public void AdvancedMultiSegmentPolylineTest() var shape = model.Instances.OfType().FirstOrDefault(); Assert.IsNotNull(shape); var geom = geomEngine.CreateSolid(shape); - Assert.IsTrue(Math.Abs(geom.Volume - 72767) < 1); + Assert.IsTrue(Math.Abs(geom.Volume.Value - 72767) < 1); } } diff --git a/Xbim.Geometry.Engine.Interop.Tests/IfcBooleanTests.cs b/Xbim.Geometry.Engine.Interop.Tests/IfcBooleanTests.cs index 0b317855d..de914ed90 100644 --- a/Xbim.Geometry.Engine.Interop.Tests/IfcBooleanTests.cs +++ b/Xbim.Geometry.Engine.Interop.Tests/IfcBooleanTests.cs @@ -218,7 +218,7 @@ public void SubtractionResultsInClosedWindow() var cutWall = transformedWall.Cut(transformedOpening, model.ModelFactors.Precision, logger).FirstOrDefault(); Assert.IsNotNull(cutWall, "Cut wall should not be null"); // note this faceted brep already has the openings cut out and we are cutting them again so the volume should not change - var volDiff = cutWall.Volume - transformedWall.Volume; + var volDiff = (cutWall.Volume - transformedWall.Volume) ?? 0; Assert.IsTrue(Math.Abs(volDiff) < 1e-5); // Assert.IsTrue(er.Entity != null, "No IfcBooleanResult found"); // var solid = geomEngine.CreateSolid(er.Entity, logger); @@ -748,17 +748,23 @@ public void IfcHalfspace_Test() var halfSpaceSolid = geomEngine.CreateSolid(halfSpace, logger); var cut = solid.Cut(halfSpaceSolid, 1e-5); Assert.IsTrue(cut.Count > 0); - Assert.IsTrue(Math.Abs((solid.Volume * .25) - cut.First.Volume) < 1e-5); + Assert.IsTrue(solid.Volume.HasValue); + Assert.IsTrue(cut.First.Volume.HasValue); + Assert.IsTrue(Math.Abs(((solid.Volume * .25) - cut.First.Volume) ?? double.NaN) < 1e-5); //move the halfspace plane up baseSurface.Position.Location.Z = 30; halfSpaceSolid = geomEngine.CreateSolid(halfSpace, logger); cut = solid.Cut(halfSpaceSolid, 1e-5); - Assert.IsTrue(Math.Abs((solid.Volume * .75) - cut.First.Volume) < 1e-5); + Assert.IsTrue(solid.Volume.HasValue); + Assert.IsTrue(cut.First.Volume.HasValue); + Assert.IsTrue(Math.Abs(((solid.Volume * .75) - cut.First.Volume) ?? double.NaN) < 1e-5); //reverse halfspace agreement halfSpace.AgreementFlag = true; halfSpaceSolid = geomEngine.CreateSolid(halfSpace, logger); cut = solid.Cut(halfSpaceSolid, 1e-5); - Assert.IsTrue(Math.Abs((solid.Volume * .25) - cut.First.Volume) < 1e-5); + Assert.IsTrue(solid.Volume.HasValue); + Assert.IsTrue(cut.First.Volume.HasValue); + Assert.IsTrue(Math.Abs(((solid.Volume * .25) - cut.First.Volume) ?? double.NaN) < 1e-5); } } @@ -797,20 +803,26 @@ public void IfcPolygonalBoundedHalfspace_Test() var halfSpaceSolid = geomEngine.CreateSolid(polygonalBoundedHalfspace, logger); var cut = solid.Cut(halfSpaceSolid, 1e-5); - Assert.IsTrue(cut.Count > 0); - Assert.IsTrue(Math.Abs((solid.Volume) - cut.First.Volume - 1000) < 1e-5); + Assert.IsTrue(cut.Count > 0); + Assert.IsTrue(solid.Volume.HasValue); + Assert.IsTrue(cut.First.Volume.HasValue); + Assert.IsTrue(Math.Abs((solid.Volume - cut.First.Volume - 1000) ?? double.NaN) < 1e-5); //reverse halfspace agreement polygonalBoundedHalfspace.AgreementFlag = true; halfSpaceSolid = geomEngine.CreateSolid(polygonalBoundedHalfspace, logger); cut = solid.Cut(halfSpaceSolid, 1e-5); - Assert.IsTrue(Math.Abs(solid.Volume - cut.First.Volume) < 1e-5); + Assert.IsTrue(solid.Volume.HasValue); + Assert.IsTrue(cut.First.Volume.HasValue); + Assert.IsTrue(Math.Abs((solid.Volume - cut.First.Volume) ?? double.NaN) < 1e-5); //move the plane up plane.Position.Location.Z = 20; halfSpaceSolid = geomEngine.CreateSolid(polygonalBoundedHalfspace, logger); - cut = solid.Cut(halfSpaceSolid, 1e-5); - Assert.IsTrue(Math.Abs(solid.Volume - cut.First.Volume - 500) < 1e-5); + cut = solid.Cut(halfSpaceSolid, 1e-5); + Assert.IsTrue(solid.Volume.HasValue); + Assert.IsTrue(cut.First.Volume.HasValue); + Assert.IsTrue(Math.Abs((solid.Volume - cut.First.Volume - 500) ?? double.NaN) < 1e-5); //some realistic data polyLine.Points[0].SetXY(0, 0); @@ -986,11 +998,11 @@ public void CuttingOpeningInCompositeProfileDefTest() Assert.IsTrue(cutSolid.IsValid); if (uncutItem.Volume <= cutSolid.Volume) uncut++; Assert.IsTrue(uncut <= 3, "More than two solids are uncut, there should only be two"); - vol += cutSolid.Volume; + vol += cutSolid.Volume ?? double.NaN; } Assert.IsTrue(uncut == 2); var scutVol = singleCut.Sum(s => s.Volume); - Assert.IsTrue(Math.Abs(vol - scutVol) < 1e-5); + Assert.IsTrue(Math.Abs((vol - scutVol) ?? double.NaN) < 1e-5); } diff --git a/Xbim.Geometry.Engine.Interop.Tests/LocationAndPlacementTests.cs b/Xbim.Geometry.Engine.Interop.Tests/LocationAndPlacementTests.cs index 767db5d9d..765e10a98 100644 --- a/Xbim.Geometry.Engine.Interop.Tests/LocationAndPlacementTests.cs +++ b/Xbim.Geometry.Engine.Interop.Tests/LocationAndPlacementTests.cs @@ -103,7 +103,7 @@ public void MoveAndCopyTest() ax3D.Location.Y = 100; var solidA = geomEngine.Moved(solid, ax3D) as IXbimSolid; Assert.IsNotNull(solidA, "Should be the same type as the master"); - Assert.IsTrue(Math.Abs(solidA.Volume - solid.Volume) < 1e-9, "Volume has changed"); + Assert.IsTrue(Math.Abs((solidA.Volume - solid.Volume) ?? double.NaN) < 1e-9, "Volume has changed"); var displacement = solidA.BoundingBox.Centroid() - solid.BoundingBox.Centroid(); Assert.IsTrue(displacement == new XbimVector3D(0, 100, 0)); var bbA = solidA.BoundingBox; @@ -228,7 +228,7 @@ public void TransformSolidRectangularProfileDef() transform.OffsetY += 200; transform.OffsetZ += 300; solid2 = (IXbimSolid)solid.Transform(transform); - Assert.IsTrue(Math.Abs(solid.Volume - solid2.Volume) < 0.001, "Volume differs"); + Assert.IsTrue(Math.Abs((solid.Volume - solid2.Volume) ?? double.NaN) < 0.001, "Volume differs"); transform.Invert(); solid2 = (IXbimSolid)solid2.Transform(transform); s1Verts = solid.Vertices.ToList(); diff --git a/Xbim.Geometry.Engine.Interop/Xbim.Geometry.Engine.Interop.csproj b/Xbim.Geometry.Engine.Interop/Xbim.Geometry.Engine.Interop.csproj index 3ac252ab9..cbc1be4bd 100644 --- a/Xbim.Geometry.Engine.Interop/Xbim.Geometry.Engine.Interop.csproj +++ b/Xbim.Geometry.Engine.Interop/Xbim.Geometry.Engine.Interop.csproj @@ -13,7 +13,7 @@ - + diff --git a/Xbim.Geometry.Engine/XbimCompound.cpp b/Xbim.Geometry.Engine/XbimCompound.cpp index d7bb03076..44a61a0e8 100644 --- a/Xbim.Geometry.Engine/XbimCompound.cpp +++ b/Xbim.Geometry.Engine/XbimCompound.cpp @@ -646,10 +646,12 @@ namespace Xbim } + void XbimCompound::Init(IIfcOpenShell^ openShell, ILogger^ logger) { Init((IIfcConnectedFaceSet^)openShell, logger); } + bool XbimCompound::Sew() { @@ -685,18 +687,30 @@ namespace Xbim return true; } - double XbimCompound::Volume::get() + Nullable XbimCompound::Volume::get() { if (IsValid) { GProp_GProps gProps; BRepGProp::VolumeProperties(*pCompound, gProps, Standard_True); GC::KeepAlive(this); - return gProps.Mass(); + double mass = gProps.Mass(); + if (0 != mass) + return Nullable(mass); } - else - return 0; + + return Nullable(); + } + + double XbimCompound::VolumeValid::get() + { + if (IsValid) + { + return Solids->VolumeValid + Shells->VolumeValid; + } + return 0; } + //This method copes with faces that may be advanced as well as ordinary TopoDS_Shape XbimCompound::InitAdvancedFaces(IEnumerable^ faces, ILogger^ logger) { diff --git a/Xbim.Geometry.Engine/XbimCompound.h b/Xbim.Geometry.Engine/XbimCompound.h index 360945b27..cbc0373fd 100644 --- a/Xbim.Geometry.Engine/XbimCompound.h +++ b/Xbim.Geometry.Engine/XbimCompound.h @@ -111,9 +111,10 @@ namespace Xbim XbimCompound^ Cut(XbimCompound^ solids, double tolerance, ILogger^ logger); XbimCompound^ Union(XbimCompound^ solids, double tolerance, ILogger^ logger); XbimCompound^ Intersection(XbimCompound^ solids, double tolerance, ILogger^ logger); - virtual property XbimRect3D BoundingBox {XbimRect3D get()override ; } - virtual property double Volume{double get(); } - virtual property double SewingTolerance {double get() {return _sewingTolerance;}} + virtual property XbimRect3D BoundingBox { XbimRect3D get() override ; } + virtual property Nullable Volume { Nullable get() override; } + virtual property double VolumeValid { double get(); } + virtual property double SewingTolerance { double get() {return _sewingTolerance;}} //moves the compound to the new positio void Move(IIfcAxis2Placement3D^ position); diff --git a/Xbim.Geometry.Engine/XbimGeometryCreator.cpp b/Xbim.Geometry.Engine/XbimGeometryCreator.cpp index 2778499ce..e6d4982fe 100644 --- a/Xbim.Geometry.Engine/XbimGeometryCreator.cpp +++ b/Xbim.Geometry.Engine/XbimGeometryCreator.cpp @@ -350,6 +350,7 @@ namespace Xbim ((XbimShapeGeometry^)shapeGeom)->BoundingBox = geometryObject->BoundingBox; ((XbimShapeGeometry^)shapeGeom)->LOD = XbimLOD::LOD_Unspecified, ((XbimShapeGeometry^)shapeGeom)->Format = storageType; + ((XbimShapeGeometry^)shapeGeom)->Volume = geometryObject->Volume; return shapeGeom; } } @@ -380,6 +381,7 @@ namespace Xbim ((XbimShapeGeometry^)shapeGeom)->BoundingBox = geometryObject->BoundingBox; ((XbimShapeGeometry^)shapeGeom)->LOD = XbimLOD::LOD_Unspecified, ((XbimShapeGeometry^)shapeGeom)->Format = storageType; + ((XbimShapeGeometry^)shapeGeom)->Volume = geometryObject->Volume; } } diff --git a/Xbim.Geometry.Engine/XbimGeometryObject.h b/Xbim.Geometry.Engine/XbimGeometryObject.h index fa8e1b4f8..24c90cd0e 100644 --- a/Xbim.Geometry.Engine/XbimGeometryObject.h +++ b/Xbim.Geometry.Engine/XbimGeometryObject.h @@ -71,6 +71,8 @@ namespace Xbim virtual property int Count {int get() abstract; } virtual IXbimGeometryObject^ Trim() abstract; virtual void Mesh(IXbimMeshReceiver^ mesh, double precision, double deflection, double angle) abstract; + // Predefined null volume, overridden by inhertance + virtual property Nullable Volume {Nullable get() { return Nullable(); }} }; ref class XbimGeometryObject abstract: IXbimGeometryObject @@ -85,16 +87,18 @@ namespace Xbim !XbimGeometryObject() {}; #pragma endregion - virtual property bool IsValid{bool get() abstract; } + virtual property bool IsValid{bool get() abstract; } virtual property bool IsSet{bool get() abstract; } - virtual property XbimGeometryObjectType GeometryType{XbimGeometryObjectType get() abstract;} + virtual property XbimGeometryObjectType GeometryType{XbimGeometryObjectType get() abstract;} virtual bool Equals(IXbimGeometryObject^ , double ){ throw gcnew NotImplementedException("Function not implemented"); } virtual bool Intersects(IXbimGeometryObject^ , double ){ throw gcnew NotImplementedException("Function not implemented"); } virtual property XbimRect3D BoundingBox {XbimRect3D get() abstract; }; virtual IXbimGeometryObject^ Transform(XbimMatrix3D matrix3D) abstract; virtual IXbimGeometryObject^ TransformShallow(XbimMatrix3D matrix3D) abstract; - virtual property String^ ToBRep{String^ get(); } - virtual property Object^ Tag {Object^ get() { return tag; }; void set(Object^ value) { tag = value; }; } + // Predefined null volume, overridden by inhertance + virtual property Nullable Volume {Nullable get() { return Nullable(); }} + virtual property String^ ToBRep{String^ get(); } + virtual property Object^ Tag {Object^ get() { return tag; }; void set(Object^ value) { tag = value; }; } }; } } diff --git a/Xbim.Geometry.Engine/XbimGeometryObjectSet.cpp b/Xbim.Geometry.Engine/XbimGeometryObjectSet.cpp index 331212bfd..35259e400 100644 --- a/Xbim.Geometry.Engine/XbimGeometryObjectSet.cpp +++ b/Xbim.Geometry.Engine/XbimGeometryObjectSet.cpp @@ -584,7 +584,6 @@ namespace Xbim return PerformBoolean(BOPAlgo_CUT, (IEnumerable^)this, gcnew XbimSolidSet(solid), tolerance, logger); } - IXbimGeometryObjectSet^ XbimGeometryObjectSet::Union(IXbimSolidSet^ solids, double tolerance, ILogger^ logger) { return PerformBoolean(BOPAlgo_FUSE, (IEnumerable^)this, solids, tolerance, logger); @@ -606,5 +605,21 @@ namespace Xbim if (Count == 0) return XbimGeometryObjectSet::Empty; return PerformBoolean(BOPAlgo_COMMON, (IEnumerable^)this, gcnew XbimSolidSet(solid), tolerance, logger); } + + double XbimGeometryObjectSet::VolumeValid::get() + { + if (IsValid) + { + double total = 0; + for each (IXbimGeometryObject ^ obj in geometryObjects) + { + Nullable vol = obj->Volume; + if (vol.HasValue) + total += vol.Value; + } + return total; + } + return 0; + } } } diff --git a/Xbim.Geometry.Engine/XbimGeometryObjectSet.h b/Xbim.Geometry.Engine/XbimGeometryObjectSet.h index ccc3f683c..11db000bc 100644 --- a/Xbim.Geometry.Engine/XbimGeometryObjectSet.h +++ b/Xbim.Geometry.Engine/XbimGeometryObjectSet.h @@ -72,6 +72,7 @@ namespace Xbim virtual IXbimGeometryObjectSet^ Intersection(IXbimSolidSet^ solids, double tolerance, ILogger^ logger); virtual IXbimGeometryObjectSet^ Intersection(IXbimSolid^ solid, double tolerance, ILogger^ logger); virtual bool Sew(); + virtual property double VolumeValid { double get(); } #pragma endregion virtual void Add(IXbimGeometryObject^ geomObj){ geometryObjects->Add(geomObj); } diff --git a/Xbim.Geometry.Engine/XbimPoint3DWithTolerance.h b/Xbim.Geometry.Engine/XbimPoint3DWithTolerance.h index ffc787668..c4a64f816 100644 --- a/Xbim.Geometry.Engine/XbimPoint3DWithTolerance.h +++ b/Xbim.Geometry.Engine/XbimPoint3DWithTolerance.h @@ -36,6 +36,8 @@ namespace Xbim virtual property double Tolerance{double get(){ return tolerance; }; } virtual property XbimPoint3D VertexGeometry {XbimPoint3D get() { return point; }; } virtual property XbimRect3D BoundingBox {XbimRect3D get(); } + virtual property Nullable Volume {Nullable get() { return Nullable(); }} + virtual IXbimGeometryObject^ Transform(XbimMatrix3D matrix3D); virtual IXbimGeometryObject^ TransformShallow(XbimMatrix3D matrix3D); virtual property String^ ToBRep{String^ get(); } diff --git a/Xbim.Geometry.Engine/XbimShell.cpp b/Xbim.Geometry.Engine/XbimShell.cpp index af3f382f4..744e54945 100644 --- a/Xbim.Geometry.Engine/XbimShell.cpp +++ b/Xbim.Geometry.Engine/XbimShell.cpp @@ -275,6 +275,20 @@ namespace Xbim } + Nullable XbimShell::Volume::get() + { + if (IsValid) + { + GProp_GProps gProps; + BRepGProp::VolumeProperties(*pShell, gProps, Standard_True); + GC::KeepAlive(this); + double mass = gProps.Mass(); + if (0 != mass) + return Nullable(mass); + } + return Nullable(); + } + IXbimGeometryObject^ XbimShell::Transform(XbimMatrix3D matrix3D) { if (!IsValid) return nullptr; diff --git a/Xbim.Geometry.Engine/XbimShell.h b/Xbim.Geometry.Engine/XbimShell.h index 0eda9e798..ee2c22335 100644 --- a/Xbim.Geometry.Engine/XbimShell.h +++ b/Xbim.Geometry.Engine/XbimShell.h @@ -57,9 +57,10 @@ namespace Xbim virtual property IXbimEdgeSet^ Edges{ IXbimEdgeSet^ get(); } virtual property IXbimVertexSet^ Vertices{IXbimVertexSet^ get(); } virtual property XbimRect3D BoundingBox{XbimRect3D get() override; } - virtual property bool IsClosed{bool get(); } + virtual property bool IsClosed { bool get(); } virtual property double SurfaceArea { double get(); } virtual property bool IsPolyhedron { bool get(); } + virtual property Nullable Volume { Nullable get() override; } virtual IXbimGeometryObjectSet^ Cut(IXbimSolidSet^ solids, double tolerance, ILogger^ logger); virtual IXbimGeometryObjectSet^ Cut(IXbimSolid^ solid, double tolerance, ILogger^ logger); virtual IXbimGeometryObjectSet^ Union(IXbimSolidSet^ solids, double tolerance, ILogger^ logger); diff --git a/Xbim.Geometry.Engine/XbimShellSet.cpp b/Xbim.Geometry.Engine/XbimShellSet.cpp index 0762e3190..524e41120 100644 --- a/Xbim.Geometry.Engine/XbimShellSet.cpp +++ b/Xbim.Geometry.Engine/XbimShellSet.cpp @@ -190,5 +190,38 @@ namespace Xbim if (Count == 0) return XbimGeometryObjectSet::Empty; return XbimGeometryObjectSet::PerformBoolean(BOPAlgo_COMMON, (IEnumerable^)this, gcnew XbimSolidSet(solid), tolerance, logger); } + + Nullable XbimShellSet::Volume::get() + { + double totalVol = 0; + if (IsValid) + { + for each (XbimShell ^ shell in shells) + { + Nullable sVol = shell->Volume; + if (sVol.HasValue) + totalVol += sVol.Value; + else + // Prevent returning wrong partial values, better no value + return Nullable(); + } + } + return Nullable(totalVol); + } + + double XbimShellSet::VolumeValid::get() + { + double totalVol = 0; + if (IsValid) + { + for each (XbimShell ^ shell in shells) + { + Nullable sVol = shell->Volume; + if (sVol.HasValue) + totalVol += sVol.Value; + } + } + return totalVol; + } } } diff --git a/Xbim.Geometry.Engine/XbimShellSet.h b/Xbim.Geometry.Engine/XbimShellSet.h index ef9d4ad86..564572f02 100644 --- a/Xbim.Geometry.Engine/XbimShellSet.h +++ b/Xbim.Geometry.Engine/XbimShellSet.h @@ -56,8 +56,11 @@ namespace Xbim virtual IXbimGeometryObjectSet^ Intersection(IXbimSolid^ solid, double tolerance, ILogger^ logger); virtual property bool IsPolyhedron{ bool get(); } virtual void Union(double tolerance); + + virtual property double VolumeValid { double get(); } #pragma endregion + virtual property Nullable Volume { Nullable get() override; } // Inherited via XbimSetObject virtual IXbimGeometryObject ^ Transformed(IIfcCartesianTransformationOperator ^ transformation) override; diff --git a/Xbim.Geometry.Engine/XbimSolid.cpp b/Xbim.Geometry.Engine/XbimSolid.cpp index 4ee75dd1e..e6fe4ab69 100644 --- a/Xbim.Geometry.Engine/XbimSolid.cpp +++ b/Xbim.Geometry.Engine/XbimSolid.cpp @@ -2056,17 +2056,19 @@ namespace Xbim return true; } - double XbimSolid::Volume::get() + Nullable XbimSolid::Volume::get() { if (IsValid) { GProp_GProps gProps; BRepGProp::VolumeProperties(*pSolid, gProps); GC::KeepAlive(this); - return gProps.Mass(); + double mass = gProps.Mass(); + if (0 != mass) + return Nullable(mass); } - else - return 0; + + return Nullable(); } bool XbimSolid::IsPolyhedron::get() diff --git a/Xbim.Geometry.Engine/XbimSolid.h b/Xbim.Geometry.Engine/XbimSolid.h index f0bb336d4..0add5ed26 100644 --- a/Xbim.Geometry.Engine/XbimSolid.h +++ b/Xbim.Geometry.Engine/XbimSolid.h @@ -92,9 +92,9 @@ namespace Xbim virtual property IXbimFaceSet^ Faces { IXbimFaceSet^ get(); } virtual property IXbimEdgeSet^ Edges { IXbimEdgeSet^ get(); } virtual property IXbimVertexSet^ Vertices {IXbimVertexSet^ get(); } - virtual property XbimRect3D BoundingBox {XbimRect3D get() override; } + virtual property XbimRect3D BoundingBox {XbimRect3D get() override;} virtual property bool IsClosed {bool get(); } - virtual property double Volume {double get(); } + virtual property Nullable Volume { Nullable get() override; } virtual property double SurfaceArea { double get(); } virtual property bool IsPolyhedron { bool get(); } virtual property bool HasValidTopology {bool get(); } diff --git a/Xbim.Geometry.Engine/XbimSolidSet.cpp b/Xbim.Geometry.Engine/XbimSolidSet.cpp index 25bd5926f..bda1f2f1a 100644 --- a/Xbim.Geometry.Engine/XbimSolidSet.cpp +++ b/Xbim.Geometry.Engine/XbimSolidSet.cpp @@ -301,17 +301,37 @@ namespace Xbim return solids == nullptr ? 0 : solids->Count; } - double XbimSolidSet::Volume::get() + Nullable XbimSolidSet::Volume::get() { - double vol = 0; + double totalVol = 0; if (IsValid) { for each (XbimSolid ^ solid in solids) { - vol += solid->Volume; + Nullable sVol = solid->Volume; + if (sVol.HasValue) + totalVol += sVol.Value; + else + // Prevent returning wrong partial values, better no value + return Nullable(); + } + } + return Nullable(totalVol); + } + + double XbimSolidSet::VolumeValid::get() + { + double totalVol = 0; + if (IsValid) + { + for each (XbimSolid ^ solid in solids) + { + Nullable sVol = solid->Volume; + if (sVol.HasValue) + totalVol += sVol.Value; } } - return vol; + return totalVol; } IXbimGeometryObject^ XbimSolidSet::Transform(XbimMatrix3D matrix3D) @@ -1003,7 +1023,8 @@ namespace Xbim XbimSolidSet^ basic = dynamic_cast(set); if (basic != nullptr) { - return basic->Volume; + Nullable vol = basic->Volume; + return vol.HasValue ? vol.Value : 0; } return ret; } diff --git a/Xbim.Geometry.Engine/XbimSolidSet.h b/Xbim.Geometry.Engine/XbimSolidSet.h index 06e0defe2..eb760a96b 100644 --- a/Xbim.Geometry.Engine/XbimSolidSet.h +++ b/Xbim.Geometry.Engine/XbimSolidSet.h @@ -133,7 +133,8 @@ namespace Xbim virtual property bool IsPolyhedron{ bool get(); } virtual IXbimGeometryObject^ Transform(XbimMatrix3D matrix3D) ; virtual IXbimGeometryObject^ TransformShallow(XbimMatrix3D matrix3D); - virtual property double Volume{double get(); } + virtual property Nullable Volume { Nullable get() override; } + virtual property double VolumeValid { double get(); } virtual IXbimSolidSet^ Range(int start, int count); //moves the solid set to the new position void Move(IIfcAxis2Placement3D^ position); diff --git a/Xbim.Geometry.Regression/XbimRegression.csproj b/Xbim.Geometry.Regression/XbimRegression.csproj index bf73e6d60..2853841ab 100644 --- a/Xbim.Geometry.Regression/XbimRegression.csproj +++ b/Xbim.Geometry.Regression/XbimRegression.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/Xbim.ModelGeometry.Scene/Xbim.ModelGeometry.Scene.csproj b/Xbim.ModelGeometry.Scene/Xbim.ModelGeometry.Scene.csproj index d3511c8e7..5df6f2c45 100644 --- a/Xbim.ModelGeometry.Scene/Xbim.ModelGeometry.Scene.csproj +++ b/Xbim.ModelGeometry.Scene/Xbim.ModelGeometry.Scene.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/Xbim.ModelGeometry.Scene/Xbim3DModelContext.cs b/Xbim.ModelGeometry.Scene/Xbim3DModelContext.cs index 6f8482b06..468248950 100644 --- a/Xbim.ModelGeometry.Scene/Xbim3DModelContext.cs +++ b/Xbim.ModelGeometry.Scene/Xbim3DModelContext.cs @@ -943,7 +943,8 @@ private HashSet WriteProductsWithFeatures(XbimCreateContextHelper contextHe GeometryHash = 0, LOD = XbimLOD.LOD_Unspecified, Format = geomType, - BoundingBox = elementGeom.BoundingBox + BoundingBox = elementGeom.BoundingBox, + Volume = geom.Volume }; var memStream = new MemoryStream(0x4000); @@ -1297,7 +1298,7 @@ private void WriteShapeGeometries(XbimCreateContextHelper contextHelper, ReportP var localPercentageParsed = contextHelper.PercentageParsed; var localTally = contextHelper.Tally; // var dedupCount = 0; - var xbimTessellator = new XbimTessellator(Model, geomStorageType); + var xbimTessellator = new XbimTessellator(Model, geomStorageType, _logger); //var geomHash = new ConcurrentDictionary(); //var mapLookup = new ConcurrentDictionary(); @@ -1389,7 +1390,6 @@ private void WriteShapeGeometries(XbimCreateContextHelper contextHelper, ReportP } if (geomModel != null && geomModel.IsValid) { - shapeGeom = Engine.CreateShapeGeometry(geomModel, precision, deflection, deflectionAngle, geomStorageType, _logger); if (isFeatureElementShape) {