1 // Copyright (c) 2021 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <BinTools_ShapeReader.hxx>
16 #include <BRep_PointOnCurve.hxx>
17 #include <BRep_PointOnCurveOnSurface.hxx>
18 #include <BRep_PointOnSurface.hxx>
19 #include <BRep_Polygon3D.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BinTools_CurveSet.hxx>
22 #include <BinTools_Curve2dSet.hxx>
23 #include <BinTools_SurfaceSet.hxx>
25 //=======================================================================
26 //function : BinTools_ShapeReader
28 //=======================================================================
29 BinTools_ShapeReader::BinTools_ShapeReader()
32 //=======================================================================
33 //function : ~BinTools_ShapeReader
35 //=======================================================================
36 BinTools_ShapeReader::~BinTools_ShapeReader()
39 //=======================================================================
42 //=======================================================================
43 void BinTools_ShapeReader::Clear()
45 BinTools_ShapeSetBase::Clear();
47 myLocationPos.Clear();
51 myPolygon3dPos.Clear();
53 myTriangulationPos.Clear();
56 //=======================================================================
59 //=======================================================================
60 void BinTools_ShapeReader::Read (Standard_IStream& theStream, TopoDS_Shape& theShape)
62 BinTools_IStream aStream(theStream);
63 theShape = ReadShape(aStream);
66 //=======================================================================
67 //function : ReadShape
69 //=======================================================================
70 TopoDS_Shape BinTools_ShapeReader::ReadShape (BinTools_IStream& theStream)
73 uint64_t aPosition = theStream.Position();
74 const BinTools_ObjectType& aType = theStream.ReadType();
75 if (aType == BinTools_ObjectType_EmptyShape || aType == BinTools_ObjectType_EndShape)
78 if (theStream.IsReference())
80 uint64_t aRef = theStream.ReadReference();
81 const TopoDS_Shape* aFound = myShapePos.Seek(aRef);
82 if (aFound) // the shape is already retrieved, just add location
88 uint64_t aCurrent = theStream.Position();
89 theStream.GoTo (aRef); // go to the referenced position
90 aResult = ReadShape (theStream);
91 theStream.GoTo (aCurrent); // returns to the current position
93 aResult.Location (*ReadLocation (theStream));
94 aResult.Orientation (TopAbs_Orientation (theStream.ReadByte()));
98 TopAbs_ShapeEnum aShapeType = theStream.ShapeType();
99 TopAbs_Orientation aShapeOrientation = theStream.ShapeOrientation();
100 const TopLoc_Location* aShapeLocation = ReadLocation (theStream);
102 static BRep_Builder aBuilder;
105 switch (aShapeType) {
108 TopoDS_Vertex& aV = TopoDS::Vertex (aResult);
109 // Read the point geometry
111 gp_Pnt aPnt = theStream.ReadPnt();
112 aBuilder.MakeVertex (aV, aPnt, aTol);
113 Handle(BRep_TVertex) aTV = Handle(BRep_TVertex)::DownCast (aV.TShape());
114 BRep_ListOfPointRepresentation& aLpr = aTV->ChangePoints();
115 static TopLoc_Location anEmptyLoc;
117 Standard_Byte aPrsType = theStream.ReadByte();
118 if (aPrsType == 0) // end of the cycle
120 Standard_Real aParam = theStream.ReadReal();
121 Handle(BRep_PointRepresentation) aPR;
125 Handle(Geom_Curve) aCurve = ReadCurve (theStream);
126 if (!aCurve.IsNull())
127 aPR = new BRep_PointOnCurve (aParam, aCurve, anEmptyLoc);
132 Handle(Geom2d_Curve) aCurve2d = ReadCurve2d (theStream);
133 Handle(Geom_Surface) aSurface = ReadSurface (theStream);
134 if (!aCurve2d.IsNull() && aSurface.IsNull())
135 aPR = new BRep_PointOnCurveOnSurface (aParam, aCurve2d, aSurface, anEmptyLoc);
140 Standard_Real aParam2 = theStream.ReadReal();
141 Handle(Geom_Surface) aSurface = ReadSurface (theStream);
142 if (!aSurface.IsNull())
143 aPR = new BRep_PointOnSurface (aParam, aParam2, aSurface, anEmptyLoc);
148 Standard_SStream aMsg;
149 aMsg << "BinTools_ShapeReader::Read: UnExpected BRep_PointRepresentation = " << aPrsType << std::endl;
150 throw Standard_Failure (aMsg.str().c_str());
153 const TopLoc_Location* aPRLoc = ReadLocation (theStream);
156 aPR->Location (*aPRLoc);
164 TopoDS_Edge& aE = TopoDS::Edge (aResult);
165 aBuilder.MakeEdge(aE);
166 // Read the curve geometry
168 Standard_Boolean aSameParameter, aSameRange, aDegenerated;
169 theStream.ReadBools (aSameParameter, aSameRange, aDegenerated);
170 aBuilder.SameParameter (aE, aSameParameter);
171 aBuilder.SameRange (aE, aSameRange);
172 aBuilder.Degenerated (aE, aDegenerated);
173 Standard_Real aFirst, aLast;
175 Standard_Byte aPrsType = theStream.ReadByte(); //{0|1|2|3|4|5|6|7}
180 case 1: // -1- Curve 3D
182 Handle(Geom_Curve) aCurve = ReadCurve (theStream);
183 const TopLoc_Location* aLoc = ReadLocation (theStream);
186 if (!aCurve.IsNull())
188 aBuilder.UpdateEdge (aE, aCurve, *aLoc, aTol);
189 aBuilder.Range (aE, aFirst, aLast, Standard_True);
193 case 2: // -2- Curve on surf
194 case 3: // -3- Curve on closed surf
196 Standard_Boolean aClosed = (aPrsType == 3);
197 Handle(Geom2d_Curve) aCurve2d_2, aCurve2d_1 = ReadCurve2d (theStream);
198 GeomAbs_Shape aReg = GeomAbs_C0;
200 aCurve2d_2 = ReadCurve2d (theStream);
201 aReg = (GeomAbs_Shape)theStream.ReadByte();
203 Handle(Geom_Surface) aSurface = ReadSurface (theStream);
204 const TopLoc_Location* aLoc = ReadLocation (theStream);
208 if (!aCurve2d_1.IsNull() && (!aClosed || !aCurve2d_2.IsNull()) && !aSurface.IsNull())
212 aBuilder.UpdateEdge (aE, aCurve2d_1, aCurve2d_2, aSurface, *aLoc, aTol);
213 aBuilder.Continuity (aE, aSurface, aSurface, *aLoc, *aLoc, aReg);
216 aBuilder.UpdateEdge (aE, aCurve2d_1, aSurface, *aLoc, aTol);
217 aBuilder.Range (aE, aSurface, *aLoc, aFirst, aLast);
221 case 4: // -4- Regularity
223 GeomAbs_Shape aReg = (GeomAbs_Shape)theStream.ReadByte();
224 Handle(Geom_Surface) aSurface1 = ReadSurface (theStream);
225 const TopLoc_Location* aLoc1 = ReadLocation (theStream);
226 Handle(Geom_Surface) aSurface2 = ReadSurface (theStream);
227 const TopLoc_Location* aLoc2 = ReadLocation (theStream);
228 if (!aSurface1.IsNull() && !aSurface2.IsNull())
229 aBuilder.Continuity (aE, aSurface1, aSurface2, *aLoc1, *aLoc2, aReg);
232 case 5: // -5- Polygon3D
234 Handle(Poly_Polygon3D) aPolygon = ReadPolygon3d (theStream);
235 const TopLoc_Location* aLoc = ReadLocation (theStream);
236 aBuilder.UpdateEdge (aE, aPolygon, *aLoc);
239 case 6: // -6- Polygon on triangulation
240 case 7: // -7- Polygon on closed triangulation
242 Standard_Boolean aClosed = (aPrsType == 7);
243 Handle(Poly_PolygonOnTriangulation) aPoly2, aPoly1 = ReadPolygon (theStream);
245 aPoly2 = ReadPolygon (theStream);
246 Handle(Poly_Triangulation) aTriangulation = ReadTriangulation (theStream);
247 const TopLoc_Location* aLoc = ReadLocation (theStream);
249 aBuilder.UpdateEdge (aE, aPoly1, aPoly2, aTriangulation, *aLoc);
251 aBuilder.UpdateEdge (aE, aPoly1, aTriangulation, *aLoc);
257 Standard_SStream aMsg;
258 aMsg << "Unexpected Curve Representation =" << aPrsType << std::endl;
259 throw Standard_Failure (aMsg.str().c_str());
267 aBuilder.MakeWire (TopoDS::Wire (aResult));
271 TopoDS_Face& aF = TopoDS::Face (aResult);
272 aBuilder.MakeFace (aF);
273 Standard_Boolean aNatRes = theStream.ReadBool();
275 Handle(Geom_Surface) aSurface = ReadSurface (theStream);
276 const TopLoc_Location* aLoc = ReadLocation (theStream);
277 aBuilder.UpdateFace (aF, aSurface, *aLoc, aTol);
278 aBuilder.NaturalRestriction (aF, aNatRes);
279 if (theStream.ReadByte() == 2) // triangulation
280 aBuilder.UpdateFace (aF, ReadTriangulation (theStream));
284 aBuilder.MakeShell (TopoDS::Shell (aResult));
287 aBuilder.MakeSolid (TopoDS::Solid (aResult));
289 case TopAbs_COMPSOLID:
290 aBuilder.MakeCompSolid (TopoDS::CompSolid (aResult));
292 case TopAbs_COMPOUND:
293 aBuilder.MakeCompound (TopoDS::Compound (aResult));
297 Standard_SStream aMsg;
298 aMsg << "Unexpected topology type = " << aShapeType << std::endl;
299 throw Standard_Failure (aMsg.str().c_str());
304 catch (Standard_Failure const& anException)
306 Standard_SStream aMsg;
307 aMsg << "EXCEPTION in BinTools_ShapeReader::Read" << std::endl;
308 aMsg << anException << std::endl;
309 throw Standard_Failure (aMsg.str().c_str());
311 // read flags and subs
312 Standard_Boolean aFree, aMod, aChecked, anOrient, aClosed, anInf, aConv;
313 theStream.ReadBools (aFree, aMod, aChecked, anOrient, aClosed, anInf, aConv);
315 for(TopoDS_Shape aSub = ReadShape (theStream); !aSub.IsNull(); aSub = ReadShape (theStream))
316 aBuilder.Add (aResult, aSub);
317 aResult.Free (aFree);
318 aResult.Modified (aMod);
319 aResult.Checked (aChecked);
320 aResult.Orientable (anOrient);
321 aResult.Closed (aClosed);
322 aResult.Infinite (anInf);
323 aResult.Convex (aConv);
324 myShapePos.Bind (aPosition, aResult);
325 aResult.Orientation (aShapeOrientation);
326 aResult.Location (*aShapeLocation);
330 //=======================================================================
331 //function : ReadLocation
333 //=======================================================================
334 const TopLoc_Location* BinTools_ShapeReader::ReadLocation (BinTools_IStream& theStream)
336 static const TopLoc_Location* anEmptyLoc = new TopLoc_Location;
338 uint64_t aPosition = theStream.Position();
339 const BinTools_ObjectType& aType = theStream.ReadType();
340 if (aType == BinTools_ObjectType_EmptyLocation || aType == BinTools_ObjectType_LocationEnd)
342 if (theStream.IsReference())
344 uint64_t aRef = theStream.ReadReference();
345 const TopLoc_Location* aFound = myLocationPos.Seek (aRef);
346 if (aFound) // the location is already retrieved
348 uint64_t aCurrent = theStream.Position();
349 theStream.GoTo (aRef); // go to the referenced position
350 const TopLoc_Location* aResult = ReadLocation (theStream);
351 theStream.GoTo (aCurrent); // returns to the current position
354 // read the location directly from the stream
355 TopLoc_Location aLoc;
356 if (aType == BinTools_ObjectType_SimpleLocation)
362 else if (aType == BinTools_ObjectType_Location)
364 for(const TopLoc_Location* aNextLoc = ReadLocation (theStream); !aNextLoc->IsIdentity();
365 aNextLoc = ReadLocation (theStream))
366 aLoc = aNextLoc->Powered (theStream.ReadInteger()) * aLoc;
368 myLocationPos.Bind (aPosition, aLoc);
369 return myLocationPos.Seek (aPosition);
372 //=======================================================================
373 //function : ReadCurve
375 //=======================================================================
376 Handle(Geom_Curve) BinTools_ShapeReader::ReadCurve (BinTools_IStream& theStream)
378 Handle(Geom_Curve) aResult;
379 uint64_t aPosition = theStream.Position();
380 theStream.ReadType();
381 if (theStream.IsReference())
382 { // get by reference
383 uint64_t aRef = theStream.ReadReference();
384 const Handle(Geom_Curve)* aFound = myCurvePos.Seek (aRef);
385 if (aFound) // the location is already retrieved
387 uint64_t aCurrent = theStream.Position();
388 theStream.GoTo (aRef); // go to the referenced position
389 aResult = ReadCurve (theStream);
390 theStream.GoTo (aCurrent); // returns to the current position
392 else if (theStream.LastType() == BinTools_ObjectType_Curve)
393 { // read from the stream
394 BinTools_CurveSet::ReadCurve (theStream.Stream(), aResult);
395 theStream.UpdatePosition();
396 myCurvePos.Bind (aPosition, aResult);
401 //=======================================================================
402 //function : ReadCurve2d
404 //=======================================================================
405 Handle(Geom2d_Curve) BinTools_ShapeReader::ReadCurve2d (BinTools_IStream& theStream)
407 Handle(Geom2d_Curve) aResult;
408 uint64_t aPosition = theStream.Position();
409 theStream.ReadType();
410 if (theStream.IsReference())
411 { // get by reference
412 uint64_t aRef = theStream.ReadReference();
413 const Handle(Geom2d_Curve)* aFound = myCurve2dPos.Seek (aRef);
414 if (aFound) // the location is already retrieved
416 uint64_t aCurrent = theStream.Position();
417 theStream.GoTo (aRef); // go to the referenced position
418 aResult = ReadCurve2d (theStream);
419 theStream.GoTo (aCurrent); // returns to the current position
421 else if (theStream.LastType() == BinTools_ObjectType_Curve2d)
422 { // read from the stream
423 BinTools_Curve2dSet::ReadCurve2d (theStream.Stream(), aResult);
424 theStream.UpdatePosition();
425 myCurve2dPos.Bind (aPosition, aResult);
430 //=======================================================================
431 //function : ReadSurface
433 //=======================================================================
434 Handle(Geom_Surface) BinTools_ShapeReader::ReadSurface (BinTools_IStream& theStream)
436 Handle(Geom_Surface) aResult;
437 uint64_t aPosition = theStream.Position();
438 theStream.ReadType();
439 if (theStream.IsReference())
440 { // get by reference
441 uint64_t aRef = theStream.ReadReference();
442 const Handle(Geom_Surface)* aFound = mySurfacePos.Seek (aRef);
443 if (aFound) // the location is already retrieved
445 uint64_t aCurrent = theStream.Position();
446 theStream.GoTo (aRef); // go to the referenced position
447 aResult = ReadSurface (theStream);
448 theStream.GoTo (aCurrent); // returns to the current position
450 else if (theStream.LastType() == BinTools_ObjectType_Surface)
451 { // read from the stream
452 BinTools_SurfaceSet::ReadSurface (theStream.Stream(), aResult);
453 theStream.UpdatePosition();
454 mySurfacePos.Bind (aPosition, aResult);
459 //=======================================================================
460 //function : ReadPolygon3d
462 //=======================================================================
463 Handle(Poly_Polygon3D) BinTools_ShapeReader::ReadPolygon3d (BinTools_IStream& theStream)
465 Handle(Poly_Polygon3D) aResult;
466 uint64_t aPosition = theStream.Position();
467 theStream.ReadType();
468 if (theStream.IsReference())
469 { // get by reference
470 uint64_t aRef = theStream.ReadReference();
471 const Handle(Poly_Polygon3D)* aFound = myPolygon3dPos.Seek (aRef);
472 if (aFound) // the location is already retrieved
474 uint64_t aCurrent = theStream.Position();
475 theStream.GoTo (aRef); // go to the referenced position
476 aResult = ReadPolygon3d (theStream);
477 theStream.GoTo (aCurrent); // returns to the current position
479 else if (theStream.LastType() == BinTools_ObjectType_Polygon3d)
480 { // read from the stream
481 Standard_Integer aNbNodes = theStream.ReadInteger();
482 Standard_Boolean aHasParameters = theStream.ReadBool();
483 aResult = new Poly_Polygon3D (aNbNodes, aHasParameters);
484 aResult->Deflection (theStream.ReadReal());
485 TColgp_Array1OfPnt& aNodes = aResult->ChangeNodes();
486 for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
487 theStream >> aNodes.ChangeValue (aNodeIter);
490 TColStd_Array1OfReal& aParam = aResult->ChangeParameters();
491 for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
492 theStream >> aParam.ChangeValue (aNodeIter);
494 myPolygon3dPos.Bind (aPosition, aResult);
499 //=======================================================================
500 //function : ReadPolygon
502 //=======================================================================
503 Handle(Poly_PolygonOnTriangulation) BinTools_ShapeReader::ReadPolygon (BinTools_IStream& theStream)
505 Handle(Poly_PolygonOnTriangulation) aResult;
506 uint64_t aPosition = theStream.Position();
507 theStream.ReadType();
508 if (theStream.IsReference())
509 { // get by reference
510 uint64_t aRef = theStream.ReadReference();
511 const Handle(Poly_PolygonOnTriangulation)* aFound = myPolygonPos.Seek (aRef);
512 if (aFound) // the location is already retrieved
514 uint64_t aCurrent = theStream.Position();
515 theStream.GoTo (aRef); // go to the referenced position
516 aResult = ReadPolygon (theStream);
517 theStream.GoTo (aCurrent); // returns to the current position
519 else if (theStream.LastType() == BinTools_ObjectType_PolygonOnTriangulation)
520 { // read from the stream
521 Standard_Integer aNbNodes = theStream.ReadInteger();
522 aResult = new Poly_PolygonOnTriangulation (aNbNodes, Standard_False);
523 for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
524 aResult->SetNode(aNodeIter, theStream.ReadInteger());
525 aResult->Deflection (theStream.ReadReal());
526 if (theStream.ReadBool())
528 Handle(TColStd_HArray1OfReal) aParams = new TColStd_HArray1OfReal (1, aNbNodes);
529 for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
530 theStream >> aParams->ChangeValue (aNodeIter);
531 aResult->SetParameters (aParams);
533 myPolygonPos.Bind (aPosition, aResult);
538 //=======================================================================
539 //function : ReadTriangulation
541 //=======================================================================
542 Handle(Poly_Triangulation) BinTools_ShapeReader::ReadTriangulation (BinTools_IStream& theStream)
544 Handle(Poly_Triangulation) aResult;
545 uint64_t aPosition = theStream.Position();
546 const BinTools_ObjectType& aType = theStream.ReadType();
547 if (theStream.IsReference())
548 { // get by reference
549 uint64_t aRef = theStream.ReadReference();
550 const Handle(Poly_Triangulation)* aFound = myTriangulationPos.Seek (aRef);
551 if (aFound) // the location is already retrieved
553 uint64_t aCurrent = theStream.Position();
554 theStream.GoTo (aRef); // go to the referenced position
555 aResult = ReadTriangulation (theStream);
556 theStream.GoTo (aCurrent); // returns to the current position
558 else if (aType == BinTools_ObjectType_Triangulation)
559 { // read from the stream
560 Standard_Integer aNbNodes = theStream.ReadInteger();
561 Standard_Integer aNbTriangles = theStream.ReadInteger();
562 Standard_Boolean aHasUV = theStream.ReadBool();
563 Standard_Boolean aHasNormals = theStream.ReadBool();
564 aResult = new Poly_Triangulation (aNbNodes, aNbTriangles, aHasUV, aHasNormals);
565 aResult->Deflection (theStream.ReadReal());
566 for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
567 aResult->SetNode(aNodeIter, theStream.ReadPnt());
571 for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
573 theStream >> anUV.ChangeCoord().ChangeCoord (1);
574 theStream >> anUV.ChangeCoord().ChangeCoord (2);
575 aResult->SetUVNode(aNodeIter, anUV);
578 // read the triangles
579 Poly_Triangle aTriangle;
580 for (Standard_Integer aTriIter = 1; aTriIter <= aNbTriangles; ++aTriIter)
582 theStream >> aTriangle.ChangeValue (1);
583 theStream >> aTriangle.ChangeValue (2);
584 theStream >> aTriangle.ChangeValue (3);
585 aResult->SetTriangle(aTriIter, aTriangle);
590 for (Standard_Integer aNormalIter = 1; aNormalIter <= aNbNodes; ++aNormalIter)
592 theStream >> aNormal.x();
593 theStream >> aNormal.y();
594 theStream >> aNormal.z();
595 aResult->SetNormal (aNormalIter, aNormal);
599 myTriangulationPos.Bind (aPosition, aResult);