diff --git a/Xbim.Geometry.Engine.Interop.Tests/TestFiles/composite_curve_issue_261.ifc b/Xbim.Geometry.Engine.Interop.Tests/TestFiles/composite_curve_issue_261.ifc new file mode 100644 index 000000000..c207e2551 --- /dev/null +++ b/Xbim.Geometry.Engine.Interop.Tests/TestFiles/composite_curve_issue_261.ifc @@ -0,0 +1,232 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION ((''), '2;1'); +FILE_NAME ('', '2020-04-28T12:10:14', (''), (''), 'Processor version 5.0.0.0', 'Xbim.IO.MemoryModel', ''); +FILE_SCHEMA (('IFC2X3')); +ENDSEC; +DATA; +#1=IFCCOMPOSITECURVE((#2,#8,#15,#19,#25,#31,#35,#40,#46,#50,#55,#60,#64,#68,#73,#77,#82,#87,#91,#95,#100,#104,#108,#113,#117,#121,#126,#130,#134,#139,#143,#147,#152,#156,#160,#165,#169,#173,#178,#182,#187,#192,#196),.F.); +#2=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#3); +#3=IFCTRIMMEDCURVE(#4,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(50.0000000006965)),.T.,.PARAMETER.); +#4=IFCLINE(#5,#6); +#5=IFCCARTESIANPOINT((0.,0.,0.)); +#6=IFCVECTOR(#7,1.); +#7=IFCDIRECTION((0.999999999999215,1.25306505651584E-06,3.49245254934071E-11)); +#8=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#9); +#9=IFCTRIMMEDCURVE(#10,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632677167)),.T.,.PARAMETER.); +#10=IFCCIRCLE(#11,30.); +#11=IFCAXIS2PLACEMENT3D(#12,#13,#14); +#12=IFCCARTESIANPOINT((49.9999999995551,1.40164756885497E-05,30.0000000018989)); +#13=IFCDIRECTION((1.53493365368072E-06,-0.999999999996636,-2.0910068997036E-06)); +#14=IFCDIRECTION((1.80929462523238E-07,1.43799648415969E-06,-0.99999999999895)); +#15=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#16); +#16=IFCTRIMMEDCURVE(#17,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.5707963268186)),.T.,.PARAMETER.); +#17=IFCCIRCLE(#18,30.); +#18=IFCAXIS2PLACEMENT3D(#12,#13,#7); +#19=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#20); +#20=IFCTRIMMEDCURVE(#21,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000006876)),.T.,.PARAMETER.); +#21=IFCLINE(#22,#23); +#22=IFCCARTESIANPOINT((49.9999999986908,-4.87137330935639E-05,60.000000001601)); +#23=IFCVECTOR(#24,1.); +#24=IFCDIRECTION((-0.999999999999215,-1.25306514232965E-06,-3.50554134578805E-11)); +#25=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#26); +#26=IFCTRIMMEDCURVE(#27,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632683607)),.T.,.PARAMETER.); +#27=IFCCIRCLE(#28,30.); +#28=IFCAXIS2PLACEMENT3D(#29,#13,#30); +#29=IFCCARTESIANPOINT((-780.000000006111,-0.00125997850773274,29.9999999686622)); +#30=IFCDIRECTION((-7.6311770711312E-09,-1.43796308472523E-06,0.999999999998966)); +#31=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#32); +#32=IFCTRIMMEDCURVE(#33,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671677)),.T.,.PARAMETER.); +#33=IFCCIRCLE(#34,30.); +#34=IFCAXIS2PLACEMENT3D(#29,#13,#24); +#35=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#36); +#36=IFCTRIMMEDCURVE(#37,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000050748)),.T.,.PARAMETER.); +#37=IFCLINE(#38,#39); +#38=IFCCARTESIANPOINT((-780.000000043591,-0.00119724830085488,6.19616713493087E-09)); +#39=IFCVECTOR(#7,1.); +#40=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#41); +#41=IFCTRIMMEDCURVE(#42,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671683)),.T.,.PARAMETER.); +#42=IFCCIRCLE(#43,30.); +#43=IFCAXIS2PLACEMENT3D(#44,#45,#30); +#44=IFCCARTESIANPOINT((50.0000000061672,0.000139476887909495,-29.999999991404)); +#45=IFCDIRECTION((-1.53493371287315E-06,0.999999999996636,2.09100689982117E-06)); +#46=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#47); +#47=IFCTRIMMEDCURVE(#48,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.5707963268731)),.T.,.PARAMETER.); +#48=IFCCIRCLE(#49,30.); +#49=IFCAXIS2PLACEMENT3D(#44,#45,#7); +#50=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#51); +#51=IFCTRIMMEDCURVE(#52,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000010356)),.T.,.PARAMETER.); +#52=IFCLINE(#53,#54); +#53=IFCCARTESIANPOINT((50.0000000126015,0.000202207094901041,-59.9999999848882)); +#54=IFCVECTOR(#24,1.); +#55=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#56); +#56=IFCTRIMMEDCURVE(#57,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632687285)),.T.,.PARAMETER.); +#57=IFCCIRCLE(#58,30.); +#58=IFCAXIS2PLACEMENT3D(#59,#13,#30); +#59=IFCCARTESIANPOINT((-779.999999996792,-0.00100905767979498,-89.9999999870483)); +#60=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#61); +#61=IFCTRIMMEDCURVE(#62,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671727)),.T.,.PARAMETER.); +#62=IFCCIRCLE(#63,30.); +#63=IFCAXIS2PLACEMENT3D(#59,#13,#24); +#64=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#65); +#65=IFCTRIMMEDCURVE(#66,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000020537)),.T.,.PARAMETER.); +#66=IFCLINE(#67,#6); +#67=IFCCARTESIANPOINT((-780.000000004069,-0.000946327472831854,-119.999999979712)); +#68=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#69); +#69=IFCTRIMMEDCURVE(#70,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671727)),.T.,.PARAMETER.); +#70=IFCCIRCLE(#71,30.); +#71=IFCAXIS2PLACEMENT3D(#72,#45,#30); +#72=IFCCARTESIANPOINT((50.000000015484,0.000390397715875679,-149.999999977149)); +#73=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#74); +#74=IFCTRIMMEDCURVE(#75,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632687272)),.T.,.PARAMETER.); +#75=IFCCIRCLE(#76,30.); +#76=IFCAXIS2PLACEMENT3D(#72,#45,#7); +#77=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#78); +#78=IFCTRIMMEDCURVE(#79,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000012055)),.T.,.PARAMETER.); +#79=IFCLINE(#80,#81); +#80=IFCCARTESIANPOINT((50.0000000236123,0.000453127922384056,-179.999999968943)); +#81=IFCVECTOR(#24,1.); +#82=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#83); +#83=IFCTRIMMEDCURVE(#84,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632687303)),.T.,.PARAMETER.); +#84=IFCCIRCLE(#85,30.); +#85=IFCAXIS2PLACEMENT3D(#86,#13,#30); +#86=IFCCARTESIANPOINT((-779.999999987477,-0.000758136858621583,-209.999999971212)); +#87=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#88); +#88=IFCTRIMMEDCURVE(#89,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671677)),.T.,.PARAMETER.); +#89=IFCCIRCLE(#90,30.); +#90=IFCAXIS2PLACEMENT3D(#86,#13,#24); +#91=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#92); +#92=IFCTRIMMEDCURVE(#93,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000022394)),.T.,.PARAMETER.); +#93=IFCLINE(#94,#6); +#94=IFCCARTESIANPOINT((-779.999999996613,-0.000695406645348839,-239.999999962022)); +#95=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#96); +#96=IFCTRIMMEDCURVE(#97,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671677)),.T.,.PARAMETER.); +#97=IFCCIRCLE(#98,30.); +#98=IFCAXIS2PLACEMENT3D(#99,#45,#30); +#99=IFCCARTESIANPOINT((50.0000000247918,0.000641318529773116,-269.999999959623)); +#100=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#101); +#101=IFCTRIMMEDCURVE(#102,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632684798)),.T.,.PARAMETER.); +#102=IFCCIRCLE(#103,30.); +#103=IFCAXIS2PLACEMENT3D(#99,#45,#7); +#104=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#105); +#105=IFCTRIMMEDCURVE(#106,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000014769)),.T.,.PARAMETER.); +#106=IFCLINE(#107,#54); +#107=IFCCARTESIANPOINT((50.0000000348932,0.000704048736281493,-299.999999950195)); +#108=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#109); +#109=IFCTRIMMEDCURVE(#110,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632684779)),.T.,.PARAMETER.); +#110=IFCCIRCLE(#111,30.); +#111=IFCAXIS2PLACEMENT3D(#112,#13,#30); +#112=IFCCARTESIANPOINT((-779.999999978158,-0.000507216038386105,-329.999999973254)); +#113=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#114); +#114=IFCTRIMMEDCURVE(#115,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671708)),.T.,.PARAMETER.); +#115=IFCCIRCLE(#116,30.); +#116=IFCAXIS2PLACEMENT3D(#112,#13,#24); +#117=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#118); +#118=IFCTRIMMEDCURVE(#119,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000045739)),.T.,.PARAMETER.); +#119=IFCLINE(#120,#39); +#120=IFCCARTESIANPOINT((-780.000000010641,-0.000444485830996655,-359.999999940715)); +#121=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#122); +#122=IFCTRIMMEDCURVE(#123,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.5707963267169)),.T.,.PARAMETER.); +#123=IFCCIRCLE(#124,30.); +#124=IFCAXIS2PLACEMENT3D(#125,#45,#30); +#125=IFCCARTESIANPOINT((50.0000000341123,0.000892239371324877,-389.999999938206)); +#126=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#127); +#127=IFCTRIMMEDCURVE(#128,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632687303)),.T.,.PARAMETER.); +#128=IFCCIRCLE(#129,30.); +#129=IFCAXIS2PLACEMENT3D(#125,#45,#7); +#130=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#131); +#131=IFCTRIMMEDCURVE(#132,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000015602)),.T.,.PARAMETER.); +#132=IFCLINE(#133,#81); +#133=IFCCARTESIANPOINT((50.0000000457892,0.000954969578799592,-419.999999926452)); +#134=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#135); +#135=IFCTRIMMEDCURVE(#136,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.5707963268729)),.T.,.PARAMETER.); +#136=IFCCIRCLE(#137,30.); +#137=IFCAXIS2PLACEMENT3D(#138,#13,#30); +#138=IFCCARTESIANPOINT((-779.999999968847,-0.000256295203172385,-449.99999992872)); +#139=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#140); +#140=IFCTRIMMEDCURVE(#141,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671695)),.T.,.PARAMETER.); +#141=IFCCIRCLE(#142,30.); +#142=IFCAXIS2PLACEMENT3D(#138,#13,#24); +#143=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#144); +#144=IFCTRIMMEDCURVE(#145,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000026012)),.T.,.PARAMETER.); +#145=IFCLINE(#146,#6); +#146=IFCCARTESIANPOINT((-779.999999981592,-0.00019356500300205,-479.99999991592)); +#147=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#148); +#148=IFCTRIMMEDCURVE(#149,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671695)),.T.,.PARAMETER.); +#149=IFCCIRCLE(#150,30.); +#150=IFCAXIS2PLACEMENT3D(#151,#45,#30); +#151=IFCCARTESIANPOINT((50.0000000434328,0.0011431601920151,-509.999999913466)); +#152=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#153); +#153=IFCTRIMMEDCURVE(#154,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632687284)),.T.,.PARAMETER.); +#154=IFCCIRCLE(#155,30.); +#155=IFCAXIS2PLACEMENT3D(#151,#45,#7); +#156=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#157); +#157=IFCTRIMMEDCURVE(#158,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000017407)),.T.,.PARAMETER.); +#158=IFCLINE(#159,#23); +#159=IFCCARTESIANPOINT((50.0000000569123,0.00120589039272545,-539.999999899911)); +#160=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#161); +#161=IFCTRIMMEDCURVE(#162,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632687284)),.T.,.PARAMETER.); +#162=IFCCIRCLE(#163,30.); +#163=IFCAXIS2PLACEMENT3D(#164,#13,#30); +#164=IFCCARTESIANPOINT((-779.999999959526,-5.37437568937094E-06,-569.999999902234)); +#165=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#166); +#166=IFCTRIMMEDCURVE(#167,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671702)),.T.,.PARAMETER.); +#167=IFCCIRCLE(#168,30.); +#168=IFCAXIS2PLACEMENT3D(#164,#13,#24); +#169=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#170); +#170=IFCTRIMMEDCURVE(#171,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000027747)),.T.,.PARAMETER.); +#171=IFCLINE(#172,#6); +#172=IFCCARTESIANPOINT((-779.999999974015,5.73558244809647E-05,-599.999999887687)); +#173=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#174); +#174=IFCTRIMMEDCURVE(#175,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632671702)),.T.,.PARAMETER.); +#175=IFCCIRCLE(#176,30.); +#176=IFCAXIS2PLACEMENT3D(#177,#45,#30); +#177=IFCCARTESIANPOINT((50.000000052746,0.0013940810131885,-629.999999885179)); +#178=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#179); +#179=IFCTRIMMEDCURVE(#180,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632687284)),.T.,.PARAMETER.); +#180=IFCCIRCLE(#181,30.); +#181=IFCAXIS2PLACEMENT3D(#177,#45,#7); +#182=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#183); +#183=IFCTRIMMEDCURVE(#184,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(830.000000020899)),.T.,.PARAMETER.); +#184=IFCLINE(#185,#186); +#185=IFCCARTESIANPOINT((50.0000000680901,0.00145681122018004,-659.999999869759)); +#186=IFCVECTOR(#24,1.); +#187=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#188); +#188=IFCTRIMMEDCURVE(#189,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632681858)),.T.,.PARAMETER.); +#189=IFCCIRCLE(#190,30.); +#190=IFCAXIS2PLACEMENT3D(#191,#45,#14); +#191=IFCCARTESIANPOINT((-779.999999951821,0.000120086031500932,-629.999999872213)); +#192=IFCCOMPOSITECURVESEGMENT(.CONTINUOUS.,.T.,#193); +#193=IFCTRIMMEDCURVE(#194,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.57079632677046)),.T.,.PARAMETER.); +#194=IFCCIRCLE(#195,30.); +#195=IFCAXIS2PLACEMENT3D(#191,#45,#24); +#196=IFCCOMPOSITECURVESEGMENT(.DISCONTINUOUS.,.T.,#197); +#197=IFCTRIMMEDCURVE(#171,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(50.000000000928)),.T.,.PARAMETER.); +#198=IFCPROJECT('1EVvgQI8b09w9KP51HvyfM',#209,'Viaduc du Cher',$,$,$,$,(#210),#214); +#199=IFCOWNERHISTORY(#202,#203,$,.ADDED.,1588075815,$,$,0); +#200=IFCPERSON($,'Steve','',$,$,$,$,$); +#201=IFCORGANIZATION($,'Unspecified',$,$,$); +#202=IFCPERSONANDORGANIZATION(#200,#201,$); +#203=IFCAPPLICATION(#201,'Unspecified','Unspecified',$); +#204=IFCOWNERHISTORY(#205,#208,$,.NOCHANGE.,$,$,$,1489153534); +#205=IFCPERSONANDORGANIZATION(#206,#207,$); +#206=IFCPERSON('VINCIC-FR\\nicolas.legain','Undefined',$,$,$,$,$,$); +#207=IFCORGANIZATION($,'Trimble Solutions Corporation',$,$,$); +#208=IFCAPPLICATION(#207,'2016 Service Pack 5','Tekla Structures','Multi material modeling'); +#209=IFCOWNERHISTORY(#202,#203,$,.MODIFIED.,1588075815,$,$,0); +#210=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#211,$); +#211=IFCAXIS2PLACEMENT3D(#5,#212,#213); +#212=IFCDIRECTION((0.,0.,1.)); +#213=IFCDIRECTION((1.,0.,0.)); +#214=IFCUNITASSIGNMENT((#215,#216,#217,#218,#219,#220,#221,#222,#223)); +#215=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.); +#216=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.); +#217=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.); +#218=IFCSIUNIT(*,.MASSUNIT.,.KILO.,.GRAM.); +#219=IFCSIUNIT(*,.TIMEUNIT.,$,.SECOND.); +#220=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.); +#221=IFCSIUNIT(*,.SOLIDANGLEUNIT.,$,.STERADIAN.); +#222=IFCSIUNIT(*,.THERMODYNAMICTEMPERATUREUNIT.,$,.DEGREE_CELSIUS.); +#223=IFCSIUNIT(*,.LUMINOUSINTENSITYUNIT.,$,.LUMEN.); +ENDSEC; +END-ISO-10303-21; diff --git a/Xbim.Geometry.Engine.Interop.Tests/WireAndFaceTests.cs b/Xbim.Geometry.Engine.Interop.Tests/WireAndFaceTests.cs index 1595de501..356c4520a 100644 --- a/Xbim.Geometry.Engine.Interop.Tests/WireAndFaceTests.cs +++ b/Xbim.Geometry.Engine.Interop.Tests/WireAndFaceTests.cs @@ -32,6 +32,17 @@ static public void Cleanup() geomEngine = null; logger = null; } + + [TestMethod] + public void Composite_curve_issue_261() + { + using (var model = MemoryModel.OpenRead(@"TestFiles\Composite_curve_issue_261.ifc")) + { + var composite_curve = model.Instances.OfType().FirstOrDefault(); + var wire = geomEngine.CreateWire(composite_curve); + } + } + [TestMethod] public void TestIfFaceIsPlanar() { diff --git a/Xbim.Geometry.Engine.Interop.Tests/Xbim.Geometry.Engine.Interop.Tests.csproj b/Xbim.Geometry.Engine.Interop.Tests/Xbim.Geometry.Engine.Interop.Tests.csproj index 424c19542..90eeb4142 100644 --- a/Xbim.Geometry.Engine.Interop.Tests/Xbim.Geometry.Engine.Interop.Tests.csproj +++ b/Xbim.Geometry.Engine.Interop.Tests/Xbim.Geometry.Engine.Interop.Tests.csproj @@ -54,6 +54,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Xbim.Geometry.Engine/Factories/WireFactory.cpp b/Xbim.Geometry.Engine/Factories/WireFactory.cpp new file mode 100644 index 000000000..9b8bfdc74 --- /dev/null +++ b/Xbim.Geometry.Engine/Factories/WireFactory.cpp @@ -0,0 +1,9 @@ +#include "WireFactory.h" + + +// Builds a wire from a list of contiguous edges, duplicate vertices at nodes are removed +int WireFactory::Make(TopTools_ListOfShape& edgeList, TopoDS_Wire& resultWire) +{ + + return 0; +} diff --git a/Xbim.Geometry.Engine/Factories/WireFactory.h b/Xbim.Geometry.Engine/Factories/WireFactory.h new file mode 100644 index 000000000..508e93694 --- /dev/null +++ b/Xbim.Geometry.Engine/Factories/WireFactory.h @@ -0,0 +1,11 @@ +#pragma once +#include +#include +#include +class WireFactory +{ +public: + // Builds a wire from a list of contiguous edges, duplicate vertices at nodes are removed + static int Make(TopTools_ListOfShape& edgeList, TopoDS_Wire& resultWire); +}; + diff --git a/Xbim.Geometry.Engine/Xbim.Geometry.Engine.vcxproj b/Xbim.Geometry.Engine/Xbim.Geometry.Engine.vcxproj index 8b6854742..013a20fa4 100644 --- a/Xbim.Geometry.Engine/Xbim.Geometry.Engine.vcxproj +++ b/Xbim.Geometry.Engine/Xbim.Geometry.Engine.vcxproj @@ -180,6 +180,7 @@ Create Create + @@ -188,6 +189,7 @@ + diff --git a/Xbim.Geometry.Engine/Xbim.Geometry.Engine.vcxproj.filters b/Xbim.Geometry.Engine/Xbim.Geometry.Engine.vcxproj.filters index 224af5c11..1ae187e8c 100644 --- a/Xbim.Geometry.Engine/Xbim.Geometry.Engine.vcxproj.filters +++ b/Xbim.Geometry.Engine/Xbim.Geometry.Engine.vcxproj.filters @@ -9423,6 +9423,9 @@ Header Files + + Header Files + @@ -15317,6 +15320,9 @@ Source Files + + Source Files + diff --git a/Xbim.Geometry.Engine/XbimWire.cpp b/Xbim.Geometry.Engine/XbimWire.cpp index 6d9378f95..8e98bf7be 100644 --- a/Xbim.Geometry.Engine/XbimWire.cpp +++ b/Xbim.Geometry.Engine/XbimWire.cpp @@ -12,7 +12,7 @@ #include #include #include -#include + #include #include #include @@ -129,7 +129,7 @@ namespace Xbim } XbimWire::XbimWire(double precision) { Init(precision); } XbimWire::XbimWire(IIfcCurve^ profile, ILogger^ logger, XbimConstraints constraints) { Init(profile, logger, constraints); } - + XbimWire::XbimWire(IIfcCompositeCurve^ compCurve, ILogger^ logger, XbimConstraints constraints) { Init(compCurve, logger, constraints); } XbimWire::XbimWire(IIfcCompositeCurveSegment^ profile, ILogger^ logger, XbimConstraints constraints) { Init(profile, logger, constraints); }; XbimWire::XbimWire(IIfcPolyline^ profile, ILogger^ logger, XbimConstraints constraints) { Init(profile, logger, constraints); } @@ -408,13 +408,13 @@ namespace Xbim XbimGeometryCreator::LogWarning(logger, pline, "Polyline with less than 2 points is an empty line. It has been ignored"); return; } - + bool done = false; bool tryAgain = true; while (!done) { - + TColgp_SequenceOfPnt pointSeq; BRepBuilderAPI_MakeWire wireMaker; @@ -427,14 +427,14 @@ namespace Xbim bool close = (constraints & XbimConstraints::Closed) == XbimConstraints::Closed; bool notSelfIntersecting = (constraints & XbimConstraints::NotSelfIntersecting) == XbimConstraints::NotSelfIntersecting; bool isClosed = XbimFace::RemoveDuplicatePoints(pointSeq, close, tolerance); - + if (pointSeq.Length() < 2) { XbimGeometryCreator::LogWarning(logger, pline, "Polyline with less than 2 points is an empty line. It has been ignored"); return; } - + BRepBuilderAPI_MakePolygon polyMaker; for (int i = 1; i <= pointSeq.Length(); ++i) @@ -450,7 +450,7 @@ namespace Xbim if (notSelfIntersecting) {//check for no self intersection TopoDS_Wire wire = polyMaker.Wire(); //get a handle to the wire to avoid garbage collection - + //double tolerance = profile->Model->ModelFactors->Precision; Handle(Geom_Plane) planeSurface = new Geom_Plane(gp_Pnt(0, 0, 0), gp_Vec(0, 0, 1)); ShapeAnalysis_Wire wireChecker; @@ -473,11 +473,11 @@ namespace Xbim wireFixer.FixIntersectingEdgesMode() = true; wireFixer.FixNonAdjacentIntersectingEdgesMode() = true; wireFixer.ModifyTopologyMode() = true; - + bool fixed = wireFixer.Perform(); if (!fixed) // we have a self intersection but the tools cannot fix it, normally means two points are too near { - + tolerance = pline->Model->ModelFactors->OneMilliMeter / 10; //use a normal modelling precision @@ -540,7 +540,7 @@ namespace Xbim int pointCount = coordList->Count; TColgp_Array1OfPnt poles(1, pointCount); int n = 1; - for each (IItemSet^ coll in coordList) + for each (IItemSet ^ coll in coordList) { IEnumerator^ enumer = coll->GetEnumerator(); enumer->MoveNext(); @@ -806,7 +806,7 @@ namespace Xbim } } } - + void XbimWire::Init(IIfcCurve^ curve, ILogger^ logger, XbimConstraints constraints) { @@ -842,121 +842,190 @@ namespace Xbim void XbimWire::Init(IIfcCompositeCurve^ cCurve, ILogger^ logger, XbimConstraints constraints) { double tolerance = cCurve->Model->ModelFactors->Precision; - BRepBuilderAPI_MakeWire converter; + //BRepBuilderAPI_MakeWire converter; ShapeFix_ShapeTolerance fTol; double fiveMilli = 5 * cCurve->Model->ModelFactors->OneMilliMeter; //we are going to accept that a gap of 5mm is not a gap - gp_Pnt resultWireFirst; - gp_Pnt resultWireLast; + + bool firstPass = true; bool isContinuous = true; //assume continuous or closed unless last segment is discontinuous int segCount = cCurve->Segments->Count; int segIdx = 1; - - for each (IIfcCompositeCurveSegment ^ seg in cCurve->Segments) //every segment shall be a bounded curve - { - bool lastSeg = (segIdx == segCount); - - if (!dynamic_cast(seg->ParentCurve)) + BRep_Builder builder; + TopoDS_Wire resultWire; + builder.MakeWire(resultWire); + + for each (IIfcCompositeCurveSegment ^ seg in cCurve->Segments) //every segment shall be a bounded curve { - XbimGeometryCreator::LogWarning(logger, seg, "Composite curve contains a segment with is not a bounded curve. It has been ignored"); - return; - } - XbimWire^ segWire = gcnew XbimWire(seg, logger, constraints); + bool lastSeg = (segIdx == segCount); + + if (!dynamic_cast(seg->ParentCurve)) + { + XbimGeometryCreator::LogWarning(logger, seg, "Composite curve contains a segment with is not a bounded curve. It has been ignored"); + continue; + } - if (lastSeg && seg->Transition == IfcTransitionCode::DISCONTINUOUS) isContinuous = false; - if (segWire->IsValid) - { - gp_Pnt segWireFirst = segWire->StartPoint; - gp_Pnt segWireLast = segWire->EndPoint; + if (lastSeg && seg->Transition == IfcTransitionCode::DISCONTINUOUS) isContinuous = false; - if (!firstPass) + XbimWire^ xbimWire = gcnew XbimWire(seg, logger, constraints); + if (xbimWire->IsValid ) { - //simple clockwise end of last wire to start of first - double distFirstToLast = segWireFirst.Distance(resultWireLast); - double distLastToLast = segWireLast.Distance(resultWireLast); - if (!(distFirstToLast <= tolerance || distLastToLast <= tolerance)) + TopoDS_Wire segWire = xbimWire; + for (BRepTools_WireExplorer wireEx(segWire); wireEx.More(); wireEx.Next()) { - //see if the nearest is within 5mm - - if (distFirstToLast <= fiveMilli) + if (firstPass) { - fTol.LimitTolerance(segWire->StartVertex, distFirstToLast + tolerance); + builder.Add(resultWire, TopoDS::Edge(wireEx.Current())); + firstPass = false; + continue; } - else if (distLastToLast <= fiveMilli) - { - fTol.LimitTolerance(segWire->EndVertex, distLastToLast + tolerance); - } - else // it will not join + else { - //see if we can reverse the segment to fit - double distLastToFirst = segWireLast.Distance(resultWireFirst); - double distFirstToFirst = segWireFirst.Distance(resultWireFirst); - if (distFirstToFirst <= tolerance || distLastToFirst <= tolerance) + TopoDS_Vertex resultWireFirstVertex; + TopoDS_Vertex resultWireLastVertex; + gp_Pnt resultWireFirstPoint; + gp_Pnt resultWireLastPoint; + TopExp::Vertices(resultWire, resultWireFirstVertex, resultWireLastVertex); + if (resultWireFirstVertex.IsNull() || resultWireLastVertex.IsNull()) //this should never happen + { + + XbimGeometryCreator::LogWarning(logger, cCurve, "Failed to build composite curve. It has been ignored"); + return; + } + if (resultWireFirstVertex.IsEqual(resultWireLastVertex)) { - segWire->Reverse(); //just reverse it and add it, it was topologivally incorrect + XbimGeometryCreator::LogWarning(logger, cCurve, "Composite curve is closed. Further segments cannot be added and are ignored"); + pWire = new TopoDS_Wire(); + *pWire = resultWire; + pWire->Closed(true); + fTol.LimitTolerance(*pWire, tolerance); + return; } + resultWireFirstPoint = BRep_Tool::Pnt(resultWireFirstVertex); + resultWireLastPoint = BRep_Tool::Pnt(resultWireLastVertex); + + TopoDS_Edge anEdge = TopoDS::Edge(wireEx.Current()); + TopoDS_Vertex edgeFirstVertex = wireEx.CurrentVertex(); + TopoDS_Vertex edgeLastVertex = TopExp::LastVertex(anEdge, Standard_True); + if (edgeFirstVertex.IsEqual(edgeLastVertex)) //get the next vertex + edgeLastVertex = TopExp::FirstVertex(anEdge, Standard_True); + gp_Pnt edgeFirstPoint = BRep_Tool::Pnt(edgeFirstVertex); + gp_Pnt edgeLastPoint = BRep_Tool::Pnt(edgeLastVertex); + //simple clockwise end of last wire to start of first + double distFirstToLast = edgeFirstPoint.Distance(resultWireLastPoint); + double distLastToLast = edgeLastPoint.Distance(resultWireLastPoint); + if (distFirstToLast <= tolerance) + ModifyWireAddEdge(resultWire, anEdge, edgeFirstVertex, edgeFirstPoint, edgeLastVertex, resultWireLastVertex, resultWireLastPoint, distFirstToLast); + else if (distLastToLast <= tolerance) + ModifyWireAddEdge(resultWire, anEdge, edgeLastVertex, edgeLastPoint, edgeFirstVertex, resultWireLastVertex, resultWireLastPoint, distLastToLast); else { - if (distFirstToFirst <= fiveMilli) - { - fTol.LimitTolerance(segWire->StartVertex, distFirstToFirst + tolerance); - segWire->Reverse(); - } - else if (distLastToFirst <= fiveMilli) - { - fTol.LimitTolerance(segWire->EndVertex, distLastToFirst + tolerance); - segWire->Reverse(); - } - else + //see if the nearest is within 5mm + if (distFirstToLast <= fiveMilli) //its going to join to the first + ModifyWireAddEdge(resultWire, anEdge, edgeFirstVertex, edgeFirstPoint, edgeLastVertex, resultWireLastVertex, resultWireLastPoint, distFirstToLast); + else if (distLastToLast <= fiveMilli) + ModifyWireAddEdge(resultWire, anEdge, edgeLastVertex, edgeLastPoint, edgeFirstVertex, resultWireLastVertex, resultWireLastPoint, distLastToLast); + else // it will not join { + //see if we can reverse the segment to fit + double distLastToFirst = edgeLastPoint.Distance(resultWireFirstPoint); + double distFirstToFirst = edgeFirstPoint.Distance(resultWireFirstPoint); + if (distLastToFirst <= tolerance) + ModifyWireAddEdge(resultWire, anEdge, edgeLastVertex, edgeLastPoint, edgeFirstVertex, resultWireFirstVertex, resultWireFirstPoint, distLastToFirst); + else if (distFirstToFirst <= tolerance) + ModifyWireAddEdge(resultWire, anEdge, edgeFirstVertex, edgeFirstPoint, edgeLastVertex, resultWireFirstVertex, resultWireFirstPoint, distFirstToFirst); + else + { + if (distFirstToFirst <= fiveMilli) + { + anEdge.Reverse(); + ModifyWireAddEdge(resultWire, anEdge, edgeFirstVertex, edgeFirstPoint, edgeLastVertex, resultWireFirstVertex, resultWireFirstPoint, distFirstToFirst); + } + else if (distLastToFirst <= fiveMilli) + { + anEdge.Reverse(); + ModifyWireAddEdge(resultWire, anEdge, edgeLastVertex, edgeLastPoint, edgeFirstVertex, resultWireFirstVertex, resultWireFirstPoint, distLastToFirst); + } + else + { #ifdef _DEBUG - //XbimWire^ currentWire = gcnew XbimWire(converter.Wire()); - + //XbimWire^ currentWire = gcnew XbimWire(resultWire); + //String^ rep = currentWire->ToBRep; #endif // _DEBUG - XbimGeometryCreator::LogWarning(logger, seg, "Unconnected composite curve segment. Curve is incomplete"); - continue; + XbimGeometryCreator::LogWarning(logger, seg, "Unconnected composite curve segment. Curve is incomplete"); + continue; + } + } } } } } + firstPass = false; } - firstPass = false; - bool ok = false; - try - { - converter.Add(segWire); - ok = converter.IsDone(); - if (ok) - { - BRepAdaptor_CompCurve cc(converter.Wire(), Standard_True); - resultWireFirst = cc.Value(cc.FirstParameter()); - resultWireLast = cc.Value(cc.LastParameter()); - } - } - catch (const std::exception&) - { - ok = false; - } - if (!ok) + else { - XbimGeometryCreator::LogWarning(logger, seg, "Failed to join composite curve segment. It has been ignored"); - return; + XbimGeometryCreator::LogWarning(logger, seg, "Invalid edge of a composite curve found. It could not be created"); } + segIdx++; + } + pWire = new TopoDS_Wire(); + *pWire = resultWire; + fTol.LimitTolerance(*pWire, tolerance); + + } + //This is going to be added to to the selected vertex and the tolerances will be adjusted. the duplicate points will be removed + void XbimWire::ModifyWireAddEdge(TopoDS_Wire& resultWire, const TopoDS_Edge& edgeToAdd, const TopoDS_Vertex& edgeVertexToJoin, gp_Pnt edgePointToJoin, const TopoDS_Vertex& + nextEdgeVertex, const TopoDS_Vertex& wireVertexToJoin, gp_Pnt wirePointToJoin, double distance) + { + + TopoDS_Shape emptyEdge = edgeToAdd.EmptyCopied(); + TopoDS_Edge myEdge = TopoDS::Edge(emptyEdge); + BRep_Builder B; + Standard_Real tolE, tolW; + tolW = BRep_Tool::Tolerance(wireVertexToJoin); + tolE = BRep_Tool::Tolerance(edgeVertexToJoin); - } - else - { - XbimGeometryCreator::LogWarning(logger, seg, "Invalid edge of a composite curve found. It could not be created"); - } - segIdx++; + + Standard_Real maxtol = .5 * (tolW + tolE + distance), cW =1, cE=0; + bool adjust = false; + if (maxtol > tolW && maxtol > tolE) + { + cW = (maxtol - tolE) / distance; + cE = 1. - cW; + adjust = true; + } + else if (maxtol > tolW) + { + maxtol = tolE; + cW = 0.; + cE = 1.; + adjust = true; + } + /*else we don't need to do this case as the wore tolerance and position is not changing + { + maxtol = tolW; + cW = 1.; + cE = 0.; + adjust = false; + }*/ + if (adjust) + { + gp_Pnt PC(cW * wirePointToJoin.X() + cE * edgePointToJoin.X(), cW * wirePointToJoin.Y() + cE * edgePointToJoin.Y(), cW * wirePointToJoin.Z() + cE * edgePointToJoin.Z()); + B.UpdateVertex(wireVertexToJoin, PC, maxtol); } - pWire = new TopoDS_Wire(); - *pWire = converter.Wire(); - fTol.LimitTolerance(*pWire, tolerance); - } + TopoDS_Vertex firstEdgeVertex = wireVertexToJoin; + firstEdgeVertex.Orientation(TopAbs_FORWARD); + B.Add(myEdge, firstEdgeVertex); + TopoDS_Vertex nextEdgeVertexCopy = nextEdgeVertex; + nextEdgeVertexCopy.Orientation(TopAbs_REVERSED); + B.Add(myEdge, nextEdgeVertexCopy); + B.Transfert(edgeToAdd, myEdge, edgeVertexToJoin, firstEdgeVertex); + B.Add(resultWire, myEdge); + + } void XbimWire::Init(IIfcPolyLoop^ polyloop, ILogger^ logger, XbimConstraints /*constraints*/) { @@ -2422,7 +2491,7 @@ namespace Xbim Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, fEdge, lEdge); // if first is < lp and last < lp then we need to do both trims on this edge - if (first > fp&& first < lp && last < lp) + if (first > fp && first < lp && last < lp) { gp_Pnt pFirst = cc.Value(first); double uOnEdgeFirst; diff --git a/Xbim.Geometry.Engine/XbimWire.h b/Xbim.Geometry.Engine/XbimWire.h index 9e908eefe..2e0ab78ab 100644 --- a/Xbim.Geometry.Engine/XbimWire.h +++ b/Xbim.Geometry.Engine/XbimWire.h @@ -8,6 +8,7 @@ #include #include #include "XbimConstraints.h" +#include using namespace System; using namespace System::Collections::Generic; @@ -32,6 +33,12 @@ namespace Xbim void set(TopoDS_Wire* val)sealed { ptrContainer = IntPtr(val); } } void InstanceCleanup(); + void ModifyWireAddEdge(TopoDS_Wire& resultWire, + const TopoDS_Edge& EE, + const TopoDS_Vertex& edgeVertexToJoin, gp_Pnt edgePointToJoin, + const TopoDS_Vertex& nextEdgeVertex, + const TopoDS_Vertex& wireVertexToJoin, gp_Pnt wirePointToJoin, + double distance); #pragma region initialisation functions void Init(double precision);