TopoShape.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) Jürgen Riegel          (juergen.riegel@web.de) 2002     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <cstdlib>
00028 # include <sstream>
00029 # include <BRepLib.hxx>
00030 # include <BSplCLib.hxx>
00031 # include <Bnd_Box.hxx>
00032 # include <BRep_Builder.hxx>
00033 # include <BRep_Tool.hxx>
00034 # include <BRepAdaptor_Curve.hxx>
00035 # include <BRepAdaptor_HCurve.hxx>
00036 # include <BRepAdaptor_Surface.hxx>
00037 # include <BRepAlgoAPI_Common.hxx>
00038 # include <BRepAlgoAPI_Cut.hxx>
00039 # include <BRepAlgoAPI_Fuse.hxx>
00040 # include <BRepAlgo_Fuse.hxx>
00041 # include <BRepAlgoAPI_Section.hxx>
00042 # include <BRepBndLib.hxx>
00043 # include <BRepBuilderAPI_GTransform.hxx>
00044 # include <BRepBuilderAPI_MakeEdge.hxx>
00045 # include <BRepBuilderAPI_MakeFace.hxx>
00046 # include <BRepBuilderAPI_MakePolygon.hxx>
00047 # include <BRepBuilderAPI_MakeVertex.hxx>
00048 # include <BRepBuilderAPI_MakeWire.hxx>
00049 # include <BRepBuilderAPI_NurbsConvert.hxx>
00050 # include <BRepBuilderAPI_FaceError.hxx>
00051 # include <BRepBuilderAPI_Copy.hxx>
00052 # include <BRepBuilderAPI_Transform.hxx>
00053 # include <BRepCheck_Analyzer.hxx>
00054 # include <BRepCheck_ListIteratorOfListOfStatus.hxx>
00055 # include <BRepCheck_Result.hxx>
00056 # include <BRepFilletAPI_MakeFillet.hxx>
00057 # include <BRepMesh.hxx>
00058 # include <BRepMesh_IncrementalMesh.hxx>
00059 # include <BRepMesh_Triangle.hxx>
00060 # include <BRepMesh_Edge.hxx>
00061 # include <BRepOffsetAPI_MakeThickSolid.hxx>
00062 # include <BRepOffsetAPI_MakeOffsetShape.hxx>
00063 # include <BRepOffsetAPI_MakePipe.hxx>
00064 # include <BRepOffsetAPI_MakePipeShell.hxx>
00065 # include <BRepOffsetAPI_Sewing.hxx>
00066 # include <BRepOffsetAPI_ThruSections.hxx>
00067 # include <BRepPrimAPI_MakePrism.hxx>
00068 # include <BRepPrimAPI_MakeRevol.hxx>
00069 # include <BRepTools.hxx>
00070 # include <BRepTools_ReShape.hxx>
00071 # include <BRepTools_ShapeSet.hxx>
00072 # include <GCE2d_MakeSegment.hxx>
00073 # include <Geom2d_Line.hxx>
00074 # include <Geom2d_TrimmedCurve.hxx>
00075 # include <GeomLProp_SLProps.hxx>
00076 # include <GeomAPI_ProjectPointOnSurf.hxx>
00077 # include <GeomFill_CorrectedFrenet.hxx>
00078 # include <GeomFill_CurveAndTrihedron.hxx>
00079 # include <GeomFill_EvolvedSection.hxx>
00080 # include <GeomFill_Pipe.hxx>
00081 # include <GeomFill_SectionLaw.hxx>
00082 # include <GeomFill_Sweep.hxx>
00083 # include <Handle_Law_BSpFunc.hxx>
00084 # include <Handle_Law_BSpline.hxx>
00085 # include <Handle_TopTools_HSequenceOfShape.hxx>
00086 # include <Law_BSpFunc.hxx>
00087 # include <Law_Linear.hxx>
00088 # include <Law_S.hxx>
00089 # include <TopTools_HSequenceOfShape.hxx>
00090 # include <Interface_Static.hxx>
00091 # include <IGESControl_Controller.hxx>
00092 # include <IGESControl_Writer.hxx>
00093 # include <IGESControl_Reader.hxx>
00094 # include <STEPControl_Writer.hxx>
00095 # include <STEPControl_Reader.hxx>
00096 # include <TopTools_MapOfShape.hxx>
00097 # include <TopoDS.hxx>
00098 # include <TopoDS_Compound.hxx>
00099 # include <TopoDS_Iterator.hxx>
00100 # include <TopoDS_Vertex.hxx>
00101 # include <TopExp.hxx>
00102 # include <TopExp_Explorer.hxx>
00103 # include <TopTools_ListIteratorOfListOfShape.hxx>
00104 # include <Geom_BezierCurve.hxx>
00105 # include <Geom_BezierSurface.hxx>
00106 # include <Geom_BSplineCurve.hxx>
00107 # include <Geom_BSplineSurface.hxx>
00108 # include <Geom_SurfaceOfLinearExtrusion.hxx>
00109 # include <Geom_SurfaceOfRevolution.hxx>
00110 # include <Geom_Circle.hxx>
00111 # include <Geom_ConicalSurface.hxx>
00112 # include <Geom_CylindricalSurface.hxx>
00113 # include <Geom_Ellipse.hxx>
00114 # include <Geom_Hyperbola.hxx>
00115 # include <Geom_Line.hxx>
00116 # include <Geom_Parabola.hxx>
00117 # include <Geom_Plane.hxx>
00118 # include <Geom_CartesianPoint.hxx>
00119 # include <Geom_SphericalSurface.hxx>
00120 # include <Geom_ToroidalSurface.hxx>
00121 # include <Poly_Triangulation.hxx>
00122 # include <Standard_Failure.hxx>
00123 # include <StlAPI_Writer.hxx>
00124 # include <Standard_Failure.hxx>
00125 # include <gp_GTrsf.hxx>
00126 # include <ShapeAnalysis_Shell.hxx>
00127 # include <ShapeBuild_ReShape.hxx>
00128 # include <ShapeFix_Edge.hxx>
00129 # include <ShapeFix_Face.hxx>
00130 # include <ShapeFix_Shell.hxx>
00131 # include <ShapeFix_Solid.hxx>
00132 # include <ShapeUpgrade_ShellSewing.hxx>
00133 # include <ShapeUpgrade_RemoveInternalWires.hxx>
00134 #endif
00135 # include <Poly_Polygon3D.hxx>
00136 # include <Poly_PolygonOnTriangulation.hxx>
00137 # include <BRepMesh.hxx>
00138 # include <BRepBuilderAPI_Sewing.hxx>
00139 # include <ShapeFix_Shape.hxx>
00140 # include <XSControl_WorkSession.hxx>
00141 # include <Transfer_TransientProcess.hxx>
00142 # include <APIHeaderSection_MakeHeader.hxx>
00143 
00144 #include <Base/Builder3D.h>
00145 #include <Base/FileInfo.h>
00146 #include <Base/Exception.h>
00147 #include <Base/Tools.h>
00148 
00149 #include "TopoShape.h"
00150 #include "CrossSection.h"
00151 #include "TopoShapeFacePy.h"
00152 #include "TopoShapeEdgePy.h"
00153 #include "TopoShapeVertexPy.h"
00154 #include "ProgressIndicator.h"
00155 
00156 using namespace Part;
00157 
00158 const char* BRepBuilderAPI_FaceErrorText(BRepBuilderAPI_FaceError et)
00159 {
00160     switch (et)
00161     {
00162     case BRepBuilderAPI_FaceDone:
00163         return "Construction was successful";
00164     case BRepBuilderAPI_NoFace:
00165         return "No face";
00166     case BRepBuilderAPI_NotPlanar:
00167         return "Face is not planar";
00168     case BRepBuilderAPI_CurveProjectionFailed:
00169         return "Curve projection failed";
00170     case BRepBuilderAPI_ParametersOutOfRange:
00171         return "Parameters out of range";
00172 #if OCC_HEX_VERSION < 0x060500
00173     case BRepBuilderAPI_SurfaceNotC2:
00174         return "Surface not C2-continous";
00175 #endif
00176     default:
00177         return "Unknown creation error";
00178     }
00179 }
00180 
00181 // ------------------------------------------------
00182 
00183 TYPESYSTEM_SOURCE(Part::ShapeSegment , Data::Segment);
00184 
00185 std::string ShapeSegment::getName() const
00186 {
00187     return std::string();
00188 }
00189 
00190 // ------------------------------------------------
00191 
00192 TYPESYSTEM_SOURCE(Part::TopoShape , Data::ComplexGeoData);
00193 
00194 TopoShape::TopoShape()
00195 {
00196 }
00197 
00198 TopoShape::~TopoShape()
00199 {
00200 }
00201 
00202 TopoShape::TopoShape(const TopoDS_Shape& shape)
00203   : _Shape(shape)
00204 {
00205 }
00206 
00207 TopoShape::TopoShape(const TopoShape& shape)
00208   : _Shape(shape._Shape)
00209 {
00210 }
00211 
00212 std::vector<const char*> TopoShape::getElementTypes(void) const
00213 {
00214     std::vector<const char*> temp(3);
00215     temp.push_back("Vertex");
00216     temp.push_back("Edge");
00217     temp.push_back("Face");
00218 
00219     return temp;
00220 }
00221 
00222 unsigned long TopoShape::countSubElements(const char* Type) const
00223 {
00224     return countSubShapes(Type);
00225 }
00226 
00227 Data::Segment* TopoShape::getSubElement(const char* Type, unsigned long n) const
00228 {
00229     std::stringstream str;
00230     str << Type << n;
00231     std::string temp = str.str();
00232     return new ShapeSegment(getSubShape(temp.c_str()));
00233 }
00234 
00235 void TopoShape::getLinesFromSubelement(const Data::Segment* element,
00236                                        std::vector<Base::Vector3d> &Points,
00237                                        std::vector<Line> &lines) const
00238 {
00239 }
00240 
00241 void TopoShape::getFacesFromSubelement(const Data::Segment* element,
00242                                        std::vector<Base::Vector3d> &Points,
00243                                        std::vector<Base::Vector3d> &PointNormals,
00244                                        std::vector<Facet> &faces) const
00245 {
00246     if (element->getTypeId() == ShapeSegment::getClassTypeId()) {
00247         const TopoDS_Shape& shape = static_cast<const ShapeSegment*>(element)->Shape;
00248         if (shape.IsNull() || shape.ShapeType() != TopAbs_FACE)
00249             return;
00250     
00251         TopLoc_Location aLoc;
00252         // doing the meshing and checking the result
00253         Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(TopoDS::Face(shape),aLoc);
00254         if (aPoly.IsNull())
00255             return;
00256 
00257         // geting the transformation of the shape/face
00258         gp_Trsf myTransf;
00259         Standard_Boolean identity = true;
00260         if (!aLoc.IsIdentity())  {
00261             identity = false;
00262             myTransf = aLoc.Transformation();
00263         }
00264 
00265         Standard_Integer i;
00266         // geting size and create the array
00267         int nbNodesInFace = aPoly->NbNodes();
00268         int nbTriInFace = aPoly->NbTriangles();
00269         Points.resize(nbNodesInFace);
00270         PointNormals.resize(nbNodesInFace); // fills up already the array
00271         faces.resize(nbTriInFace);
00272 
00273         // check orientation
00274         TopAbs_Orientation orient = shape.Orientation();
00275 
00276         // cycling through the poly mesh
00277         const Poly_Array1OfTriangle& Triangles = aPoly->Triangles();
00278         const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
00279         for (i=1; i<=nbTriInFace; i++) {
00280             // Get the triangle
00281             Standard_Integer N1,N2,N3;
00282             Triangles(i).Get(N1,N2,N3);
00283 
00284             // change orientation of the triangles
00285             if (orient != TopAbs_FORWARD) {
00286                 Standard_Integer tmp = N1;
00287                 N1 = N2;
00288                 N2 = tmp;
00289             }
00290 
00291             gp_Pnt V1 = Nodes(N1);
00292             gp_Pnt V2 = Nodes(N2);
00293             gp_Pnt V3 = Nodes(N3);
00294 
00295             // transform the vertices to the place of the face
00296             if (!identity) {
00297                 V1.Transform(myTransf);
00298                 V2.Transform(myTransf);
00299                 V3.Transform(myTransf);
00300             }
00301 
00302             // Calculate triangle normal
00303             gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z());
00304             gp_Vec Normal = (v2-v1)^(v3-v1);
00305 
00306             //Standard_Real Area = 0.5 * Normal.Magnitude();
00307 
00308             // add the triangle normal to the vertex normal for all points of this triangle
00309             PointNormals[N1-1] += Base::Vector3d(Normal.X(),Normal.Y(),Normal.Z());
00310             PointNormals[N2-1] += Base::Vector3d(Normal.X(),Normal.Y(),Normal.Z());
00311             PointNormals[N3-1] += Base::Vector3d(Normal.X(),Normal.Y(),Normal.Z());
00312 
00313             Points[N1-1].Set(V1.X(),V1.Y(),V1.Z());
00314             Points[N2-1].Set(V2.X(),V2.Y(),V2.Z());
00315             Points[N3-1].Set(V3.X(),V3.Y(),V3.Z());
00316 
00317             int j = i - 1;
00318             N1--;
00319             N2--;
00320             N3--;
00321             faces[j].I1 = N1;
00322             faces[j].I2 = N2;
00323             faces[j].I3 = N3;
00324         }
00325 
00326         // normalize all vertex normals
00327         for (i=0; i < nbNodesInFace; i++) {
00328             gp_Dir clNormal;
00329             try {
00330                 Handle_Geom_Surface Surface = BRep_Tool::Surface(TopoDS::Face(shape));
00331 
00332                 gp_Pnt vertex(Base::convertTo<gp_Pnt>(Points[i]));
00333                 GeomAPI_ProjectPointOnSurf ProPntSrf(vertex, Surface);
00334                 Standard_Real fU, fV;
00335                 ProPntSrf.Parameters(1, fU, fV);
00336 
00337                 GeomLProp_SLProps clPropOfFace(Surface, fU, fV, 2, gp::Resolution());
00338 
00339                 clNormal = clPropOfFace.Normal();
00340                 Base::Vector3d temp = Base::convertTo<Base::Vector3d>(clNormal);
00341                 if (temp * Points[i] < 0)
00342                     temp = -temp;
00343                 Points[i] = temp;
00344             }
00345             catch (...) {
00346             }
00347             Points[i].Normalize();
00348         }
00349     }
00350 }
00351 
00352 TopoDS_Shape TopoShape::getSubShape(const char* Type) const
00353 {
00354     if (!Type) return TopoDS_Shape();
00355     std::string shapetype(Type);
00356     if (shapetype.size() > 4 && shapetype.substr(0,4) == "Face") {
00357         int index=std::atoi(&shapetype[4]);
00358         TopTools_IndexedMapOfShape anIndices;
00359         TopExp::MapShapes(this->_Shape, TopAbs_FACE, anIndices);
00360         return anIndices.FindKey(index);
00361     }
00362     else if (shapetype.size() > 4 && shapetype.substr(0,4) == "Edge") {
00363         int index=std::atoi(&shapetype[4]);
00364         TopTools_IndexedMapOfShape anIndices;
00365         TopExp::MapShapes(this->_Shape, TopAbs_EDGE, anIndices);
00366         return anIndices.FindKey(index);
00367     }
00368     else if (shapetype.size() > 6 && shapetype.substr(0,6) == "Vertex") {
00369         int index=std::atoi(&shapetype[6]);
00370         TopTools_IndexedMapOfShape anIndices;
00371         TopExp::MapShapes(this->_Shape, TopAbs_VERTEX, anIndices);
00372         return anIndices.FindKey(index);
00373     }
00374 
00375     return TopoDS_Shape();
00376 }
00377 
00378 unsigned long TopoShape::countSubShapes(const char* Type) const
00379 {
00380     std::string shapetype(Type);
00381     if (shapetype == "Face") {
00382         TopTools_IndexedMapOfShape anIndices;
00383         TopExp::MapShapes(this->_Shape, TopAbs_FACE, anIndices);
00384         return anIndices.Extent();
00385     }
00386     else if (shapetype == "Edge") {
00387         TopTools_IndexedMapOfShape anIndices;
00388         TopExp::MapShapes(this->_Shape, TopAbs_EDGE, anIndices);
00389         return anIndices.Extent();
00390     }
00391     else if (shapetype == "Vertex") {
00392         TopTools_IndexedMapOfShape anIndices;
00393         TopExp::MapShapes(this->_Shape, TopAbs_VERTEX, anIndices);
00394         return anIndices.Extent();
00395     }
00396 
00397     return 0;
00398 }
00399 
00400 PyObject * TopoShape::getPySubShape(const char* Type) const
00401 {
00402     // get the shape
00403     TopoDS_Shape Shape = getSubShape(Type);
00404     // destinquish the return type
00405     std::string shapetype(Type);
00406     if (shapetype.size() > 4 && shapetype.substr(0,4) == "Face") 
00407         return new TopoShapeFacePy(new TopoShape(Shape));
00408     else if (shapetype.size() > 4 && shapetype.substr(0,4) == "Edge") 
00409         return new TopoShapeEdgePy(new TopoShape(Shape));
00410     else if (shapetype.size() > 6 && shapetype.substr(0,6) == "Vertex") 
00411         return new TopoShapeVertexPy(new TopoShape(Shape));
00412     else 
00413         return 0;
00414 
00415 }
00416 
00417 void TopoShape::operator = (const TopoShape& sh)
00418 {
00419     if (this != &sh) {
00420         this->_Shape = sh._Shape;
00421     }
00422 }
00423 
00424 void TopoShape::setTransform(const Base::Matrix4D& rclTrf)
00425 {
00426     gp_Trsf mov;
00427     mov.SetValues(rclTrf[0][0],rclTrf[0][1],rclTrf[0][2],rclTrf[0][3],
00428                   rclTrf[1][0],rclTrf[1][1],rclTrf[1][2],rclTrf[1][3],
00429                   rclTrf[2][0],rclTrf[2][1],rclTrf[2][2],rclTrf[2][3],
00430                   0.00001,0.00001);
00431     TopLoc_Location loc(mov);
00432     _Shape.Location(loc);
00433 }
00434 
00435 Base::Matrix4D TopoShape::getTransform(void) const
00436 {
00437     Base::Matrix4D mtrx;
00438     gp_Trsf Trf = _Shape.Location().Transformation();
00439 
00440     gp_Mat m = Trf._CSFDB_Getgp_Trsfmatrix();
00441     gp_XYZ p = Trf._CSFDB_Getgp_Trsfloc();
00442     Standard_Real scale = Trf._CSFDB_Getgp_Trsfscale();
00443 
00444     // set Rotation matrix
00445     mtrx[0][0] = scale * m._CSFDB_Getgp_Matmatrix(0,0);
00446     mtrx[0][1] = scale * m._CSFDB_Getgp_Matmatrix(0,1);
00447     mtrx[0][2] = scale * m._CSFDB_Getgp_Matmatrix(0,2);
00448 
00449     mtrx[1][0] = scale * m._CSFDB_Getgp_Matmatrix(1,0);
00450     mtrx[1][1] = scale * m._CSFDB_Getgp_Matmatrix(1,1);
00451     mtrx[1][2] = scale * m._CSFDB_Getgp_Matmatrix(1,2);
00452 
00453     mtrx[2][0] = scale * m._CSFDB_Getgp_Matmatrix(2,0);
00454     mtrx[2][1] = scale * m._CSFDB_Getgp_Matmatrix(2,1);
00455     mtrx[2][2] = scale * m._CSFDB_Getgp_Matmatrix(2,2);
00456 
00457     // set pos vector
00458     mtrx[0][3] = p._CSFDB_Getgp_XYZx();
00459     mtrx[1][3] = p._CSFDB_Getgp_XYZy();
00460     mtrx[2][3] = p._CSFDB_Getgp_XYZz();
00461 
00462     return mtrx;
00463 }
00464 
00465 void TopoShape::read(const char *FileName)
00466 {
00467     Base::FileInfo File(FileName);
00468   
00469     // checking on the file
00470     if (!File.isReadable())
00471         throw Base::FileException("File to load not existing or not readable", FileName);
00472     
00473     if (File.hasExtension("igs") || File.hasExtension("iges")) {
00474         // read iges file
00475         importIges(File.filePath().c_str());
00476     }
00477     else if (File.hasExtension("stp") || File.hasExtension("step")) {
00478         importStep(File.filePath().c_str());
00479     }
00480     else if (File.hasExtension("brp") || File.hasExtension("brep")) {
00481         // read brep-file
00482         importBrep(File.filePath().c_str());
00483     }
00484     else{
00485         throw Base::Exception("Unknown extension");
00486     }
00487 }
00488 
00526 void TopoShape::importIges(const char *FileName)
00527 {
00528     try {
00529         // read iges file
00530         // http://www.opencascade.org/org/forum/thread_20801/
00531         IGESControl_Controller::Init();
00532         Interface_Static::SetIVal("read.surfacecurve.mode",3);
00533         IGESControl_Reader aReader;
00534         if (aReader.ReadFile((const Standard_CString)FileName) != IFSelect_RetDone)
00535             throw Base::Exception("Error in reading IGES");
00536 
00537         Handle_Message_ProgressIndicator pi = new ProgressIndicator(100);
00538         pi->NewScope(100, "Reading IGES file...");
00539         pi->Show();
00540         aReader.WS()->MapReader()->SetProgress(pi);
00541 
00542         // make brep
00543         aReader.ClearShapes();
00544         aReader.TransferRoots();
00545         // one shape that contains all subshapes
00546         this->_Shape = aReader.OneShape();
00547         pi->EndScope();
00548     }
00549     catch (Standard_Failure) {
00550         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00551         throw Base::Exception(aFail->GetMessageString());
00552     }
00553 }
00554 
00555 void TopoShape::importStep(const char *FileName)
00556 {
00557     try {
00558         STEPControl_Reader aReader;
00559         if (aReader.ReadFile((const Standard_CString)FileName) != IFSelect_RetDone)
00560             throw Base::Exception("Error in reading STEP");
00561 
00562         Handle_Message_ProgressIndicator pi = new ProgressIndicator(100);
00563         aReader.WS()->MapReader()->SetProgress(pi);
00564         pi->NewScope(100, "Reading STEP file...");
00565         pi->Show();
00566 
00567         // Root transfers
00568         aReader.TransferRoots();
00569         // one shape that contains all subshapes
00570         this->_Shape = aReader.OneShape();
00571         pi->EndScope();
00572     }
00573     catch (Standard_Failure) {
00574         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00575         throw Base::Exception(aFail->GetMessageString());
00576     }
00577 }
00578 
00579 void TopoShape::importBrep(const char *FileName)
00580 {
00581     try {
00582         // read brep-file
00583         BRep_Builder aBuilder;
00584         TopoDS_Shape aShape;
00585     #if OCC_HEX_VERSION >= 0x060300
00586         Handle_Message_ProgressIndicator pi = new ProgressIndicator(100);
00587         pi->NewScope(100, "Reading BREP file...");
00588         pi->Show();
00589         BRepTools::Read(aShape,(const Standard_CString)FileName,aBuilder,pi);
00590         pi->EndScope();
00591     #else
00592         BRepTools::Read(aShape,(const Standard_CString)FileName,aBuilder);
00593     #endif
00594         this->_Shape = aShape;
00595     }
00596     catch (Standard_Failure) {
00597         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00598         throw Base::Exception(aFail->GetMessageString());
00599     }
00600 }
00601 
00602 void TopoShape::write(const char *FileName) const
00603 {
00604     Base::FileInfo File(FileName);
00605     
00606     if (File.hasExtension("igs") || File.hasExtension("iges")) {
00607         // write iges file
00608         exportIges(File.filePath().c_str());
00609     }
00610     else if (File.hasExtension("stp") || File.hasExtension("step")) {
00611         exportStep(File.filePath().c_str());
00612     }
00613     else if (File.hasExtension("brp") || File.hasExtension("brep")) {
00614         // read brep-file
00615         exportBrep(File.filePath().c_str());
00616     }
00617     else if (File.hasExtension("stl")) {
00618         // read brep-file
00619         exportStl(File.filePath().c_str());
00620     }
00621     else{
00622         throw Base::Exception("Unknown extension");
00623     }
00624 }
00625 
00626 void TopoShape::exportIges(const char *filename) const
00627 {
00628     Interface_Static::SetCVal("write.iges.unit","IN");
00629     try {
00630         // write iges file
00631         IGESControl_Controller::Init();
00632         IGESControl_Writer aWriter;
00633         //IGESControl_Writer aWriter(Interface_Static::CVal("write.iges.unit"), 1);
00634         aWriter.AddShape(this->_Shape);
00635         aWriter.ComputeModel();
00636         if (aWriter.Write((const Standard_CString)filename) != IFSelect_RetDone)
00637             throw Base::Exception("Writing of IGES failed");
00638     }
00639     catch (Standard_Failure) {
00640         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00641         throw Base::Exception(aFail->GetMessageString());
00642     }
00643 }
00644 
00645 void TopoShape::exportStep(const char *filename) const
00646 {
00647     try {
00648         // write step file
00649         STEPControl_Writer aWriter;
00650 
00651         Handle_Message_ProgressIndicator pi = new ProgressIndicator(100);
00652         aWriter.WS()->MapReader()->SetProgress(pi);
00653         pi->NewScope(100, "Writing STEP file...");
00654         pi->Show();
00655 
00656         if (aWriter.Transfer(this->_Shape, STEPControl_AsIs) != IFSelect_RetDone)
00657             throw Base::Exception("Error in transferring STEP");
00658 
00659         APIHeaderSection_MakeHeader makeHeader(aWriter.Model());
00660         makeHeader.SetName(new TCollection_HAsciiString((const Standard_CString)filename));
00661         makeHeader.SetAuthorValue (1, new TCollection_HAsciiString("FreeCAD"));
00662         makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString("FreeCAD"));
00663         makeHeader.SetOriginatingSystem(new TCollection_HAsciiString("FreeCAD"));
00664         makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model"));
00665 
00666         if (aWriter.Write((const Standard_CString)filename) != IFSelect_RetDone)
00667             throw Base::Exception("Writing of STEP failed");
00668         pi->EndScope();
00669     }
00670     catch (Standard_Failure) {
00671         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00672         throw Base::Exception(aFail->GetMessageString());
00673     }
00674 }
00675 
00676 void TopoShape::exportBrep(const char *filename) const
00677 {
00678     if (!BRepTools::Write(this->_Shape,(const Standard_CString)filename))
00679         throw Base::Exception("Writing of BREP failed");
00680 }
00681 
00682 void TopoShape::exportStl(const char *filename) const
00683 {
00684     StlAPI_Writer writer;
00685     //writer.RelativeMode() = false;
00686     //writer.SetDeflection(0.1);
00687     writer.Write(this->_Shape,(const Standard_CString)filename);
00688 }
00689 
00690 void TopoShape::exportFaceSet(double dev, double ca, std::ostream& str) const
00691 {
00692     Base::InventorBuilder builder(str);
00693     TopExp_Explorer ex;
00694 
00695     BRepMesh_IncrementalMesh MESH(this->_Shape,dev);
00696     for (ex.Init(this->_Shape, TopAbs_FACE); ex.More(); ex.Next()) {
00697         // get the shape and mesh it
00698         const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
00699         Standard_Integer nbNodesInFace,nbTriInFace;
00700         std::vector<Base::Vector3f> vertices;
00701         std::vector<int> indices;
00702 
00703         // doing the meshing and checking the result
00704         TopLoc_Location aLoc;
00705         Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
00706         if (aPoly.IsNull()) continue;
00707 
00708         // getting the transformation of the shape/face
00709         gp_Trsf myTransf;
00710         Standard_Boolean identity = true;
00711         if (!aLoc.IsIdentity()) {
00712             identity = false;
00713             myTransf = aLoc.Transformation();
00714         }
00715 
00716         // getting size and create the array
00717         nbNodesInFace = aPoly->NbNodes();
00718         nbTriInFace = aPoly->NbTriangles();
00719         vertices.resize(nbNodesInFace);
00720         indices.resize(4*nbTriInFace);
00721 
00722         // check orientation
00723         TopAbs_Orientation orient = aFace.Orientation();
00724 
00725         // cycling through the poly mesh
00726         const Poly_Array1OfTriangle& Triangles = aPoly->Triangles();
00727         const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
00728         for (int i=1;i<=nbTriInFace;i++) {
00729             // Get the triangle
00730             Standard_Integer N1,N2,N3;
00731             Triangles(i).Get(N1,N2,N3);
00732 
00733             // change orientation of the triangles
00734             if (orient != TopAbs_FORWARD) {
00735                 Standard_Integer tmp = N1;
00736                 N1 = N2;
00737                 N2 = tmp;
00738             }
00739 
00740             gp_Pnt V1 = Nodes(N1);
00741             gp_Pnt V2 = Nodes(N2);
00742             gp_Pnt V3 = Nodes(N3);
00743 
00744             // transform the vertices to the place of the face
00745             if (!identity) {
00746                 V1.Transform(myTransf);
00747                 V2.Transform(myTransf);
00748                 V3.Transform(myTransf);
00749             }
00750 
00751             vertices[N1-1].Set((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));
00752             vertices[N2-1].Set((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z()));
00753             vertices[N3-1].Set((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z()));
00754 
00755             int j = i - 1;
00756             N1--; N2--; N3--;
00757             indices[4*j] = N1; indices[4*j+1] = N2; indices[4*j+2] = N3; indices[4*j+3] = -1;
00758         }
00759 
00760         builder.addIndexedFaceSet(vertices, indices, (float)ca);
00761     } // end of face loop
00762 }
00763 
00764 void TopoShape::exportLineSet(std::ostream& str) const
00765 {
00766     Base::InventorBuilder builder(str);
00767     // get a indexed map of edges
00768     TopTools_IndexedMapOfShape M;
00769     TopExp::MapShapes(this->_Shape, TopAbs_EDGE, M);
00770 
00771     // build up map edge->face
00772     TopTools_IndexedDataMapOfShapeListOfShape edge2Face;
00773     TopExp::MapShapesAndAncestors(this->_Shape, TopAbs_EDGE, TopAbs_FACE, edge2Face);
00774     for (int i=0; i<M.Extent(); i++)
00775     {
00776         const TopoDS_Edge& aEdge = TopoDS::Edge(M(i+1));
00777         gp_Trsf myTransf;
00778         TopLoc_Location aLoc;
00779 
00780         // try to triangulate the edge
00781         Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc);
00782 
00783         std::vector<Base::Vector3f> vertices;
00784         Standard_Integer nbNodesInFace;
00785 
00786         // triangulation succeeded?
00787         if (!aPoly.IsNull()) {
00788             if (!aLoc.IsIdentity()) {
00789                 myTransf = aLoc.Transformation();
00790             }
00791             nbNodesInFace = aPoly->NbNodes();
00792             vertices.resize(nbNodesInFace);
00793 
00794             const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
00795 
00796             gp_Pnt V;
00797             for (Standard_Integer i=0;i < nbNodesInFace;i++) {
00798                 V = Nodes(i+1);
00799                 V.Transform(myTransf);
00800                 vertices[i].Set((float)(V.X()),(float)(V.Y()),(float)(V.Z()));
00801             }
00802         }
00803         else {
00804             // the edge has not its own triangulation, but then a face the edge is attached to
00805             // must provide this triangulation
00806 
00807             // Look for one face in our map (it doesn't care which one we take)
00808             const TopoDS_Face& aFace = TopoDS::Face(edge2Face.FindFromKey(aEdge).First());
00809 
00810             // take the face's triangulation instead
00811             Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(aFace,aLoc);
00812             if (!aLoc.IsIdentity()) {
00813                 myTransf = aLoc.Transformation();
00814             }
00815 
00816             if (aPolyTria.IsNull()) break;
00817 
00818             // this holds the indices of the edge's triangulation to the actual points
00819             Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(aEdge, aPolyTria, aLoc);
00820             if (aPoly.IsNull())
00821                 continue; // polygon does not exist
00822 
00823             // getting size and create the array
00824             nbNodesInFace = aPoly->NbNodes();
00825             vertices.resize(nbNodesInFace);
00826 
00827             const TColStd_Array1OfInteger& indices = aPoly->Nodes();
00828             const TColgp_Array1OfPnt& Nodes = aPolyTria->Nodes();
00829 
00830             gp_Pnt V;
00831             int pos = 0;
00832             // go through the index array
00833             for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) {
00834                 V = Nodes(indices(i));
00835                 V.Transform(myTransf);
00836                 vertices[pos++].Set((float)(V.X()),(float)(V.Y()),(float)(V.Z()));
00837             }
00838         }
00839 
00840         builder.addLineSet(vertices, 2, 0, 0, 0);
00841     }
00842 }
00843 
00844 Base::BoundBox3d TopoShape::getBoundBox(void) const
00845 {
00846     Base::BoundBox3d box;
00847     try {
00848         // If the shape is empty an exception may be thrown
00849         Bnd_Box bounds;
00850         BRepBndLib::Add(_Shape, bounds);
00851         bounds.SetGap(0.0);
00852         Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
00853         bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
00854 
00855         box.MinX = xMin;
00856         box.MaxX = xMax;
00857         box.MinY = yMin;
00858         box.MaxY = yMax;
00859         box.MinZ = zMin;
00860         box.MaxZ = zMax;
00861     }
00862     catch (Standard_Failure) {
00863     }
00864 
00865     return box;
00866 }
00867 
00868 void TopoShape::Save (Base::Writer & writer) const
00869 {
00870 }
00871 
00872 void TopoShape::Restore(Base::XMLReader &reader)
00873 {
00874 }
00875 
00876 void TopoShape::SaveDocFile (Base::Writer &writer) const
00877 {
00878 }
00879 
00880 void TopoShape::RestoreDocFile(Base::Reader &reader)
00881 {
00882 }
00883 
00884 unsigned int TopoShape_RefCountShapes(const TopoDS_Shape& aShape)
00885 {
00886     unsigned int size = 1; // this shape
00887     TopoDS_Iterator it;
00888     // go through all direct children
00889     for (it.Initialize(aShape, false, false);it.More(); it.Next()) {
00890         size += TopoShape_RefCountShapes(it.Value());
00891     }
00892 
00893     return size;
00894 }
00895 
00896 unsigned int TopoShape::getMemSize (void) const
00897 {
00898     if (!_Shape.IsNull()) {
00899         // Count total amount of references of TopoDS_Shape objects
00900         unsigned int memsize = (sizeof(TopoDS_Shape)+sizeof(TopoDS_TShape)) * TopoShape_RefCountShapes(_Shape);
00901 
00902         // Now get a map of TopoDS_Shape objects without duplicates
00903         TopTools_IndexedMapOfShape M;
00904         TopExp::MapShapes(_Shape, M);
00905         for (int i=0; i<M.Extent(); i++) {
00906             const TopoDS_Shape& shape = M(i+1);
00907             // add the size of the underlying geomtric data
00908             Handle(TopoDS_TShape) tshape = shape.TShape();
00909             memsize += tshape->DynamicType()->Size();
00910 
00911             switch (shape.ShapeType())
00912             {
00913             case TopAbs_FACE:
00914                 {
00915                     // first, last, tolerance
00916                     memsize += 5*sizeof(Standard_Real);
00917                     const TopoDS_Face& face = TopoDS::Face(shape);
00918                     BRepAdaptor_Surface surface(face);
00919                     switch (surface.GetType())
00920                     {
00921                     case GeomAbs_Plane:
00922                         memsize += sizeof(Geom_Plane);
00923                         break;
00924                     case GeomAbs_Cylinder:
00925                         memsize += sizeof(Geom_CylindricalSurface);
00926                         break;
00927                     case GeomAbs_Cone:
00928                         memsize += sizeof(Geom_ConicalSurface);
00929                         break;
00930                     case GeomAbs_Sphere:
00931                         memsize += sizeof(Geom_SphericalSurface);
00932                         break;
00933                     case GeomAbs_Torus:
00934                         memsize += sizeof(Geom_ToroidalSurface);
00935                         break;
00936                     case GeomAbs_BezierSurface:
00937                         memsize += sizeof(Geom_BezierSurface);
00938                         memsize += (surface.NbUKnots()+surface.NbVKnots()) * sizeof(Standard_Real);
00939                         memsize += (surface.NbUPoles()*surface.NbVPoles()) * sizeof(Geom_CartesianPoint);
00940                         break;
00941                     case GeomAbs_BSplineSurface:
00942                         memsize += sizeof(Geom_BSplineSurface);
00943                         memsize += (surface.NbUKnots()+surface.NbVKnots()) * sizeof(Standard_Real);
00944                         memsize += (surface.NbUPoles()*surface.NbVPoles()) * sizeof(Geom_CartesianPoint);
00945                         break;
00946                     case GeomAbs_SurfaceOfRevolution:
00947                         memsize += sizeof(Geom_SurfaceOfRevolution);
00948                         break;
00949                     case GeomAbs_SurfaceOfExtrusion:
00950                         memsize += sizeof(Geom_SurfaceOfLinearExtrusion);
00951                         break;
00952                     case GeomAbs_OtherSurface:
00953                         // What kind of surface should this be?
00954                         memsize += sizeof(Geom_Surface);
00955                         break;
00956                     default:
00957                         break;
00958                     }
00959                 } break;
00960             case TopAbs_EDGE:
00961                 {
00962                     // first, last, tolerance
00963                     memsize += 3*sizeof(Standard_Real);
00964                     const TopoDS_Edge& edge = TopoDS::Edge(shape);
00965                     BRepAdaptor_Curve curve(edge);
00966                     switch (curve.GetType())
00967                     {
00968                     case GeomAbs_Line:
00969                         memsize += sizeof(Geom_Line);
00970                         break;
00971                     case GeomAbs_Circle:
00972                         memsize += sizeof(Geom_Circle);
00973                         break;
00974                     case GeomAbs_Ellipse:
00975                         memsize += sizeof(Geom_Ellipse);
00976                         break;
00977                     case GeomAbs_Hyperbola:
00978                         memsize += sizeof(Geom_Hyperbola);
00979                         break;
00980                     case GeomAbs_Parabola:
00981                         memsize += sizeof(Geom_Parabola);
00982                         break;
00983                     case GeomAbs_BezierCurve:
00984                         memsize += sizeof(Geom_BezierCurve);
00985                         memsize += curve.NbKnots() * sizeof(Standard_Real);
00986                         memsize += curve.NbPoles() * sizeof(Geom_CartesianPoint);
00987                         break;
00988                     case GeomAbs_BSplineCurve:
00989                         memsize += sizeof(Geom_BSplineCurve);
00990                         memsize += curve.NbKnots() * sizeof(Standard_Real);
00991                         memsize += curve.NbPoles() * sizeof(Geom_CartesianPoint);
00992                         break;
00993                     case GeomAbs_OtherCurve:
00994                         // What kind of curve should this be?
00995                         memsize += sizeof(Geom_Curve);
00996                         break;
00997                     default:
00998                         break;
00999                     }
01000                 } break;
01001             case TopAbs_VERTEX:
01002                 {
01003                     // tolerance
01004                     memsize += sizeof(Standard_Real);
01005                     memsize += sizeof(Geom_CartesianPoint);
01006                 } break;
01007             default:
01008                 break;
01009             }
01010         }
01011 
01012         // estimated memory usage
01013         return memsize;
01014     }
01015 
01016     // in case the shape is invalid
01017     return sizeof(TopoDS_Shape);
01018 }
01019 
01020 bool TopoShape::isNull() const
01021 {
01022     return this->_Shape.IsNull() ? true : false;
01023 }
01024 
01025 bool TopoShape::isValid() const
01026 {
01027     BRepCheck_Analyzer aChecker(this->_Shape);
01028     return aChecker.IsValid() ? true : false;
01029 }
01030 
01031 bool TopoShape::analyze(std::ostream& str) const
01032 {
01033     if (!this->_Shape.IsNull()) {
01034         BRepCheck_Analyzer aChecker(this->_Shape);
01035         if (!aChecker.IsValid()) {
01036             std::vector<TopoDS_Shape> shapes;
01037 
01038             TopTools_IndexedMapOfShape vertexOfShape;
01039             TopExp::MapShapes(this->_Shape, TopAbs_VERTEX, vertexOfShape);
01040             for (int i = 1; i <= vertexOfShape.Extent();++i)
01041                 shapes.push_back(vertexOfShape(i));
01042 
01043             TopTools_IndexedMapOfShape edgeOfShape;
01044             TopExp::MapShapes(this->_Shape, TopAbs_EDGE, edgeOfShape);
01045             for (int i = 1; i <= edgeOfShape.Extent();++i)
01046                 shapes.push_back(edgeOfShape(i));
01047 
01048             TopTools_IndexedMapOfShape wireOfShape;
01049             TopExp::MapShapes(this->_Shape, TopAbs_WIRE, wireOfShape);
01050             for (int i = 1; i <= wireOfShape.Extent();++i)
01051                 shapes.push_back(wireOfShape(i));
01052 
01053             TopTools_IndexedMapOfShape faceOfShape;
01054             TopExp::MapShapes(this->_Shape, TopAbs_FACE, faceOfShape);
01055             for (int i = 1; i <= faceOfShape.Extent();++i)
01056                 shapes.push_back(faceOfShape(i));
01057 
01058             TopTools_IndexedMapOfShape shellOfShape;
01059             TopExp::MapShapes(this->_Shape, TopAbs_SHELL, shellOfShape);
01060             for (int i = 1; i <= shellOfShape.Extent();++i)
01061                 shapes.push_back(shellOfShape(i));
01062 
01063             TopTools_IndexedMapOfShape solidOfShape;
01064             TopExp::MapShapes(this->_Shape, TopAbs_SOLID, solidOfShape);
01065             for (int i = 1; i <= solidOfShape.Extent();++i)
01066                 shapes.push_back(solidOfShape(i));
01067 
01068             TopTools_IndexedMapOfShape compOfShape;
01069             TopExp::MapShapes(this->_Shape, TopAbs_COMPOUND, compOfShape);
01070             for (int i = 1; i <= compOfShape.Extent();++i)
01071                 shapes.push_back(compOfShape(i));
01072 
01073             TopTools_IndexedMapOfShape compsOfShape;
01074             TopExp::MapShapes(this->_Shape, TopAbs_COMPSOLID, compsOfShape);
01075             for (int i = 1; i <= compsOfShape.Extent();++i)
01076                 shapes.push_back(compsOfShape(i));
01077 
01078             for (std::vector<TopoDS_Shape>::iterator xp = shapes.begin(); xp != shapes.end(); ++xp) {
01079                 if (!aChecker.IsValid(*xp)) {
01080                     const Handle_BRepCheck_Result& result = aChecker.Result(*xp);
01081                     if (result.IsNull())
01082                         continue;
01083                     const BRepCheck_ListOfStatus& status = result->StatusOnShape(*xp);
01084 
01085                     BRepCheck_ListIteratorOfListOfStatus it(status);
01086                     while (it.More()) {
01087                         BRepCheck_Status& val = it.Value();
01088                         switch (val)
01089                         {
01090                         case BRepCheck_NoError:
01091                             str << "No error" << std::endl;
01092                             break;
01093                         case BRepCheck_InvalidPointOnCurve:
01094                             str << "Invalid point on curve" << std::endl;
01095                             break;
01096                         case BRepCheck_InvalidPointOnCurveOnSurface:
01097                             str << "Invalid point on curve on surface" << std::endl;
01098                             break;
01099                         case BRepCheck_InvalidPointOnSurface:
01100                             str << "Invalid point on surface" << std::endl;
01101                             break;
01102                         case BRepCheck_No3DCurve:
01103                             str << "No 3D curve" << std::endl;
01104                             break;
01105                         case BRepCheck_Multiple3DCurve:
01106                             str << "Multiple 3D curve" << std::endl;
01107                             break;
01108                         case BRepCheck_Invalid3DCurve:
01109                             str << "Invalid 3D curve" << std::endl;
01110                             break;
01111                         case BRepCheck_NoCurveOnSurface:
01112                             str << "No curve on surface" << std::endl;
01113                             break;
01114                         case BRepCheck_InvalidCurveOnSurface:
01115                             str << "Invalid curve on surface" << std::endl;
01116                             break;
01117                         case BRepCheck_InvalidCurveOnClosedSurface:
01118                             str << "Invalid curve on closed surface" << std::endl;
01119                             break;
01120                         case BRepCheck_InvalidSameRangeFlag:
01121                             str << "Invalid same-range flag" << std::endl;
01122                             break;
01123                         case BRepCheck_InvalidSameParameterFlag:
01124                             str << "Invalid same-parameter flag" << std::endl;
01125                             break;
01126                         case BRepCheck_InvalidDegeneratedFlag:
01127                             str << "Invalid degenerated flag" << std::endl;
01128                             break;
01129                         case BRepCheck_FreeEdge:
01130                             str << "Free edge" << std::endl;
01131                             break;
01132                         case BRepCheck_InvalidMultiConnexity:
01133                             str << "Invalid multi-connexity" << std::endl;
01134                             break;
01135                         case BRepCheck_InvalidRange:
01136                             str << "Invalid range" << std::endl;
01137                             break;
01138                         case BRepCheck_EmptyWire:
01139                             str << "Empty wire" << std::endl;
01140                             break;
01141                         case BRepCheck_RedundantEdge:
01142                             str << "Redundant edge" << std::endl;
01143                             break;
01144                         case BRepCheck_SelfIntersectingWire:
01145                             str << "Self-intersecting wire" << std::endl;
01146                             break;
01147                         case BRepCheck_NoSurface:
01148                             str << "No surface" << std::endl;
01149                             break;
01150                         case BRepCheck_InvalidWire:
01151                             str << "Invalid wires" << std::endl;
01152                             break;
01153                         case BRepCheck_RedundantWire:
01154                             str << "Redundant wires" << std::endl;
01155                             break;
01156                         case BRepCheck_IntersectingWires:
01157                             str << "Intersecting wires" << std::endl;
01158                             break;
01159                         case BRepCheck_InvalidImbricationOfWires:
01160                             str << "Invalid imbrication of wires" << std::endl;
01161                             break;
01162                         case BRepCheck_EmptyShell:
01163                             str << "Empty shell" << std::endl;
01164                             break;
01165                         case BRepCheck_RedundantFace:
01166                             str << "Redundant face" << std::endl;
01167                             break;
01168                         case BRepCheck_UnorientableShape:
01169                             str << "Unorientable shape" << std::endl;
01170                             break;
01171                         case BRepCheck_NotClosed:
01172                             str << "Not closed" << std::endl;
01173                             break;
01174                         case BRepCheck_NotConnected:
01175                             str << "Not connected" << std::endl;
01176                             break;
01177                         case BRepCheck_SubshapeNotInShape:
01178                             str << "Sub-shape not in shape" << std::endl;
01179                             break;
01180                         case BRepCheck_BadOrientation:
01181                             str << "Bad orientation" << std::endl;
01182                             break;
01183                         case BRepCheck_BadOrientationOfSubshape:
01184                             str << "Bad orientation of sub-shape" << std::endl;
01185                             break;
01186                         case BRepCheck_InvalidToleranceValue:
01187                             str << "Invalid tolerance value" << std::endl;
01188                             break;
01189                         case BRepCheck_CheckFail:
01190                             str << "Check failed" << std::endl;
01191                             break;
01192                         default:
01193                             str << "Undetermined error" << std::endl;
01194                             break;
01195                         }
01196 
01197                         it.Next();
01198                     }
01199                 }
01200             }
01201 
01202             return false; // errors detected
01203         }
01204     }
01205 
01206     return true;
01207 }
01208 
01209 bool TopoShape::isClosed() const
01210 {
01211     return BRep_Tool::IsClosed(this->_Shape) ? true : false;
01212 }
01213 
01214 TopoDS_Shape TopoShape::cut(TopoDS_Shape shape) const
01215 {
01216     BRepAlgoAPI_Cut mkCut(this->_Shape, shape);
01217     return mkCut.Shape();
01218 }
01219 
01220 TopoDS_Shape TopoShape::common(TopoDS_Shape shape) const
01221 {
01222     BRepAlgoAPI_Common mkCommon(this->_Shape, shape);
01223     return mkCommon.Shape();
01224 }
01225 
01226 TopoDS_Shape TopoShape::fuse(TopoDS_Shape shape) const
01227 {
01228     BRepAlgoAPI_Fuse mkFuse(this->_Shape, shape);
01229     return mkFuse.Shape();
01230 }
01231 
01232 TopoDS_Shape TopoShape::oldFuse(TopoDS_Shape shape) const
01233 {
01234     BRepAlgo_Fuse mkFuse(this->_Shape, shape);
01235     return mkFuse.Shape();
01236 }
01237 
01238 TopoDS_Shape TopoShape::section(TopoDS_Shape shape) const
01239 {
01240     BRepAlgoAPI_Section mkSection(this->_Shape, shape);
01241     return mkSection.Shape();
01242 }
01243 
01244 std::list<TopoDS_Wire> TopoShape::slice(const Base::Vector3d& dir, double d) const
01245 {
01246     CrossSection cs(dir.x, dir.y, dir.z, this->_Shape);
01247     return cs.section(d);
01248 }
01249 
01250 TopoDS_Compound TopoShape::slices(const Base::Vector3d& dir, const std::vector<double>& d) const
01251 {
01252     std::vector< std::list<TopoDS_Wire> > wire_list;
01253     CrossSection cs(dir.x, dir.y, dir.z, this->_Shape);
01254     for (std::vector<double>::const_iterator jt = d.begin(); jt != d.end(); ++jt) {
01255         wire_list.push_back(cs.section(*jt));
01256     }
01257 
01258     std::vector< std::list<TopoDS_Wire> >::const_iterator ft;
01259     TopoDS_Compound comp;
01260     BRep_Builder builder;
01261     builder.MakeCompound(comp);
01262 
01263     for (ft = wire_list.begin(); ft != wire_list.end(); ++ft) {
01264         const std::list<TopoDS_Wire>& w = *ft;
01265         for (std::list<TopoDS_Wire>::const_iterator wt = w.begin(); wt != w.end(); ++wt) {
01266             if (!wt->IsNull())
01267                 builder.Add(comp, *wt);
01268         }
01269     }
01270 
01271     return comp;
01272 }
01273 
01274 TopoDS_Shape TopoShape::makePipe(const TopoDS_Shape& profile) const
01275 {
01276     if (this->_Shape.IsNull())
01277         Standard_Failure::Raise("Cannot sweep along empty spine");
01278     if (this->_Shape.ShapeType() != TopAbs_WIRE)
01279         Standard_Failure::Raise("Spine shape is not a wire");
01280     if (profile.IsNull())
01281         Standard_Failure::Raise("Cannot sweep empty profile");
01282     BRepOffsetAPI_MakePipe mkPipe(TopoDS::Wire(this->_Shape), profile);
01283     return mkPipe.Shape();
01284 }
01285 
01286 TopoDS_Shape TopoShape::makePipeShell(const TopTools_ListOfShape& profiles,
01287                                       const Standard_Boolean make_solid,
01288                                       const Standard_Boolean isFrenet) const
01289 {
01290     if (this->_Shape.IsNull())
01291         Standard_Failure::Raise("Cannot sweep along empty spine");
01292     if (this->_Shape.ShapeType() != TopAbs_WIRE)
01293         Standard_Failure::Raise("Spine shape is not a wire");
01294 
01295     BRepOffsetAPI_MakePipeShell mkPipeShell(TopoDS::Wire(this->_Shape));
01296     mkPipeShell.SetMode(isFrenet);
01297     TopTools_ListIteratorOfListOfShape it;
01298     for (it.Initialize(profiles); it.More(); it.Next()) {
01299         mkPipeShell.Add(TopoDS_Shape(it.Value()));
01300     }
01301 
01302     if (!mkPipeShell.IsReady()) Standard_Failure::Raise("shape is not ready to build");
01303     else mkPipeShell.Build();
01304 
01305     if (make_solid)     mkPipeShell.MakeSolid();
01306 
01307     return mkPipeShell.Shape();
01308 }
01309 
01310 TopoDS_Shape TopoShape::makeTube(double radius, double tol) const
01311 {
01312     // http://opencascade.blogspot.com/2009/11/surface-modeling-part3.html
01313     if (this->_Shape.IsNull())
01314         Standard_Failure::Raise("Cannot sweep along empty spine");
01315     if (this->_Shape.ShapeType() != TopAbs_EDGE)
01316         Standard_Failure::Raise("Spine shape is not an edge");
01317 
01318     const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape);
01319     BRepAdaptor_Curve path_adapt(path_edge);
01320     double umin = path_adapt.FirstParameter();
01321     double umax = path_adapt.LastParameter();
01322     Handle_Geom_Curve hPath = path_adapt.Curve().Curve();
01323 
01324     // Apply placement of the shape to the curve
01325     TopLoc_Location loc1 = path_edge.Location();
01326     hPath = Handle_Geom_Curve::DownCast(hPath->Transformed(loc1.Transformation()));
01327 
01328     if (hPath.IsNull())
01329         Standard_Failure::Raise("Invalid curve in path edge");
01330 
01331     GeomFill_Pipe mkTube(hPath, radius);
01332     mkTube.Perform(tol, Standard_False, GeomAbs_C1, BSplCLib::MaxDegree(), 1000);
01333 
01334     const Handle_Geom_Surface& surf = mkTube.Surface();
01335     double u1,u2,v1,v2;
01336     surf->Bounds(u1,u2,v1,v2);
01337 
01338     BRepBuilderAPI_MakeFace mkBuilder(surf, umin, umax, v1, v2);
01339     return mkBuilder.Face();
01340 }
01341 
01342 // for testing
01343 static Handle(Law_Function) CreateBsFunction (const Standard_Real theFirst, const Standard_Real theLast)
01344 {
01345     //Handle_Law_BSpline aBs;
01346     //Handle_Law_BSpFunc aFunc = new Law_BSpFunc (aBs, theFirst, theLast);
01347     Handle_Law_Linear aFunc = new Law_Linear();
01348     aFunc->Set(theFirst, 2.0, theLast, 3.0);
01349     return aFunc;
01350 }
01351 
01352 // for testing
01353 TopoDS_Shape TopoShape::makeTube() const
01354 {
01355     // http://opencascade.blogspot.com/2009/11/surface-modeling-part3.html
01356     Standard_Real theTol = 0.001;
01357     Standard_Boolean theIsPolynomial = Standard_True;
01358     Standard_Boolean myIsElem = Standard_True;
01359     GeomAbs_Shape theContinuity = GeomAbs_G1;
01360     Standard_Integer theMaxDegree = 3;
01361     Standard_Integer theMaxSegment = 1000;
01362 
01363     if (this->_Shape.IsNull())
01364         Standard_Failure::Raise("Cannot sweep along empty spine");
01365     if (this->_Shape.ShapeType() != TopAbs_EDGE)
01366         Standard_Failure::Raise("Spine shape is not an edge");
01367 
01368     const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape);
01369     BRepAdaptor_Curve path_adapt(path_edge);
01370 
01371     //circular profile
01372     Handle(Geom_Circle) aCirc = new Geom_Circle (gp::XOY(), 1.0);
01373     aCirc->Rotate (gp::OZ(), Standard_PI/2.);
01374 
01375     //perpendicular section
01376     Handle(BRepAdaptor_HCurve) myPath = new BRepAdaptor_HCurve(path_adapt);
01377     Handle(Law_Function) myEvol = ::CreateBsFunction (myPath->FirstParameter(), myPath->LastParameter());
01378     Handle(GeomFill_SectionLaw) aSec = new GeomFill_EvolvedSection(aCirc, myEvol);
01379     Handle(GeomFill_LocationLaw) aLoc = new GeomFill_CurveAndTrihedron(new GeomFill_CorrectedFrenet);
01380     aLoc->SetCurve (myPath);
01381 
01382     GeomFill_Sweep mkSweep (aLoc, myIsElem);
01383     mkSweep.SetTolerance (theTol);
01384     mkSweep.Build (aSec, GeomFill_Location, theContinuity, theMaxDegree, theMaxSegment);
01385     if (mkSweep.IsDone()) {
01386         Handle_Geom_Surface mySurface = mkSweep.Surface();
01387         Standard_Real myError = mkSweep.ErrorOnSurface();
01388 
01389         Standard_Real u1,u2,v1,v2;
01390         mySurface->Bounds(u1,u2,v1,v2);
01391         BRepBuilderAPI_MakeFace mkBuilder(mySurface, u1, u2, v1, v2);
01392         return mkBuilder.Shape();
01393     }
01394 
01395     return TopoDS_Shape();
01396 }
01397 
01398 TopoDS_Shape TopoShape::makeSweep(const TopoDS_Shape& profile, double tol, int fillMode) const
01399 {
01400     // http://opencascade.blogspot.com/2009/10/surface-modeling-part2.html
01401     if (this->_Shape.IsNull())
01402         Standard_Failure::Raise("Cannot sweep along empty spine");
01403     if (this->_Shape.ShapeType() != TopAbs_EDGE)
01404         Standard_Failure::Raise("Spine shape is not an edge");
01405 
01406     if (profile.IsNull())
01407         Standard_Failure::Raise("Cannot sweep with empty profile");
01408     if (profile.ShapeType() != TopAbs_EDGE)
01409         Standard_Failure::Raise("Profile shape is not an edge");
01410 
01411     const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape);
01412     const TopoDS_Edge& prof_edge = TopoDS::Edge(profile);
01413 
01414     BRepAdaptor_Curve path_adapt(path_edge);
01415     double umin = path_adapt.FirstParameter();
01416     double umax = path_adapt.LastParameter();
01417     Handle_Geom_Curve hPath = path_adapt.Curve().Curve();
01418 
01419     // Apply placement of the shape to the curve
01420     TopLoc_Location loc1 = path_edge.Location();
01421     hPath = Handle_Geom_Curve::DownCast(hPath->Transformed(loc1.Transformation()));
01422 
01423     if (hPath.IsNull())
01424         Standard_Failure::Raise("invalid curve in path edge");
01425 
01426     BRepAdaptor_Curve prof_adapt(prof_edge);
01427     double vmin = prof_adapt.FirstParameter();
01428     double vmax = prof_adapt.LastParameter();
01429     Handle_Geom_Curve hProfile = prof_adapt.Curve().Curve();
01430 
01431     // Apply placement of the shape to the curve
01432     TopLoc_Location loc2 = prof_edge.Location();
01433     hProfile = Handle_Geom_Curve::DownCast(hProfile->Transformed(loc2.Transformation()));
01434 
01435     if (hProfile.IsNull())
01436         Standard_Failure::Raise("invalid curve in profile edge");
01437 
01438     GeomFill_Pipe mkSweep(hPath, hProfile, (GeomFill_Trihedron)fillMode);
01439     mkSweep.GenerateParticularCase(Standard_True);
01440     mkSweep.Perform(tol, Standard_False, GeomAbs_C1, BSplCLib::MaxDegree(), 1000);
01441 
01442     const Handle_Geom_Surface& surf = mkSweep.Surface();
01443     BRepBuilderAPI_MakeFace mkBuilder(surf, umin, umax, vmin, vmax);
01444     return mkBuilder.Face();
01445 }
01446 
01447 TopoDS_Shape TopoShape::makeHelix(Standard_Real pitch, Standard_Real height,
01448                                   Standard_Real radius, Standard_Real angle) const
01449 {
01450         if (pitch < Precision::Confusion())
01451             Standard_Failure::Raise("Pitch of helix too small");
01452 
01453         if (height < Precision::Confusion())
01454             Standard_Failure::Raise("Height of helix too small");
01455 
01456         if (radius < Precision::Confusion())
01457             Standard_Failure::Raise("Radius of helix too small");
01458 
01459         gp_Ax2 cylAx2(gp_Pnt(0.0,0.0,0.0) , gp::DZ());
01460         Handle_Geom_Surface surf;
01461         if (angle < Precision::Confusion()) {
01462             surf = new Geom_CylindricalSurface(cylAx2, radius);
01463         }
01464         else {
01465             angle = Base::toRadians(angle);
01466             if (angle < Precision::Confusion())
01467                 Standard_Failure::Raise("Angle of helix too small");
01468             surf = new Geom_ConicalSurface(gp_Ax3(cylAx2), angle, radius);
01469         }
01470 
01471         gp_Pnt2d aPnt(0, 0);
01472         gp_Dir2d aDir(2. * PI, pitch);
01473         gp_Ax2d aAx2d(aPnt, aDir);
01474 
01475         Handle(Geom2d_Line) line = new Geom2d_Line(aAx2d);
01476         gp_Pnt2d beg = line->Value(0);
01477         gp_Pnt2d end = line->Value(sqrt(4.0*PI*PI+pitch*pitch)*(height/pitch));
01478         Handle(Geom2d_TrimmedCurve) segm = GCE2d_MakeSegment(beg , end);
01479 
01480         TopoDS_Edge edgeOnSurf = BRepBuilderAPI_MakeEdge(segm , surf);
01481         TopoDS_Wire wire = BRepBuilderAPI_MakeWire(edgeOnSurf);
01482         BRepLib::BuildCurves3d(wire);
01483         return wire;
01484 }
01485 
01486 TopoDS_Shape TopoShape::makeLoft(const TopTools_ListOfShape& profiles, 
01487                                  Standard_Boolean isSolid,
01488                                  Standard_Boolean isRuled) const
01489 {
01490     // http://opencascade.blogspot.com/2010/01/surface-modeling-part5.html
01491     BRepOffsetAPI_ThruSections aGenerator (isSolid,isRuled);
01492 
01493     int countShapes = 0;
01494     TopTools_ListIteratorOfListOfShape it;
01495     for (it.Initialize(profiles); it.More(); it.Next()) {
01496         const TopoDS_Shape& item = it.Value();
01497         if (!item.IsNull() && item.ShapeType() == TopAbs_VERTEX) {
01498             aGenerator.AddVertex(TopoDS::Vertex (item));
01499             countShapes++;
01500         }
01501         else if (!item.IsNull() && item.ShapeType() == TopAbs_WIRE) {
01502             aGenerator.AddWire(TopoDS::Wire (item));
01503             countShapes++;
01504         }
01505     }
01506 
01507     if (countShapes < 2)
01508         Standard_Failure::Raise("Need at least two vertexes or wires to create loft face");
01509 
01510     Standard_Boolean anIsCheck = Standard_True;
01511     aGenerator.CheckCompatibility (anIsCheck);
01512     aGenerator.Build();
01513     if (!aGenerator.IsDone())
01514         Standard_Failure::Raise("Failed to create loft face");
01515 
01516     return aGenerator.Shape();
01517 }
01518 
01519 TopoDS_Shape TopoShape::makePrism(const gp_Vec& vec) const
01520 {
01521     if (this->_Shape.IsNull()) Standard_Failure::Raise("cannot sweep empty shape");
01522     BRepPrimAPI_MakePrism mkPrism(this->_Shape, vec);
01523     return mkPrism.Shape();
01524 }
01525 
01526 TopoDS_Shape TopoShape::revolve(const gp_Ax1& axis, double d) const
01527 {
01528     if (this->_Shape.IsNull()) Standard_Failure::Raise("cannot sweep empty shape");
01529     BRepPrimAPI_MakeRevol mkRevol(this->_Shape, axis,d);
01530     return mkRevol.Shape();
01531 }
01532 
01533 TopoDS_Shape TopoShape::makeThickSolid(const TopTools_ListOfShape& remFace,
01534                                        Standard_Real offset, Standard_Real tolerance) const
01535 {
01536     BRepOffsetAPI_MakeThickSolid mkThick(this->_Shape, remFace, offset, tolerance);
01537     return mkThick.Shape();
01538 }
01539 
01540 TopoDS_Shape TopoShape::makeOffset(double offset, double tol, bool intersection,
01541                                    bool selfInter, short offsetMode, short join)
01542 {
01543     BRepOffsetAPI_MakeOffsetShape mkOffset(this->_Shape, offset, tol, BRepOffset_Mode(offsetMode),
01544         intersection ? Standard_True : Standard_False,
01545         selfInter ? Standard_True : Standard_False,
01546         GeomAbs_JoinType(join));
01547     return mkOffset.Shape();
01548 }
01549 
01550 void TopoShape::transformGeometry(const Base::Matrix4D &rclMat)
01551 {
01552     this->_Shape = transformGShape(rclMat);
01553 }
01554 
01555 TopoDS_Shape TopoShape::transformGShape(const Base::Matrix4D& rclTrf) const
01556 {
01557     // There is a strange behaviour of the gp_Trsf class if rclTrf has
01558     // a negative determinant.
01559     gp_GTrsf mat;
01560     if (rclTrf.determinant() < 0.0) {
01561         //mat.SetValues(-rclTrf[0][0],rclTrf[0][1],rclTrf[0][2],rclTrf[0][3],
01562         //              -rclTrf[1][0],rclTrf[1][1],rclTrf[1][2],rclTrf[1][3],
01563         //              -rclTrf[2][0],rclTrf[2][1],rclTrf[2][2],rclTrf[2][3],
01564         //              0.00001,0.00001);
01565         mat.SetValue(1,1,-rclTrf[0][0]);
01566         mat.SetValue(2,1,-rclTrf[1][0]);
01567         mat.SetValue(3,1,-rclTrf[2][0]);
01568         mat.SetValue(1,2,rclTrf[0][1]);
01569         mat.SetValue(2,2,rclTrf[1][1]);
01570         mat.SetValue(3,2,rclTrf[2][1]);
01571         mat.SetValue(1,3,rclTrf[0][2]);
01572         mat.SetValue(2,3,rclTrf[1][2]);
01573         mat.SetValue(3,3,rclTrf[2][2]);
01574         mat.SetValue(1,4,rclTrf[0][3]);
01575         mat.SetValue(2,4,rclTrf[1][3]);
01576         mat.SetValue(3,4,rclTrf[2][3]);
01577     }
01578     else {
01579         //mat.SetValues(rclTrf[0][0],rclTrf[0][1],rclTrf[0][2],rclTrf[0][3],
01580         //              rclTrf[1][0],rclTrf[1][1],rclTrf[1][2],rclTrf[1][3],
01581         //              rclTrf[2][0],rclTrf[2][1],rclTrf[2][2],rclTrf[2][3],
01582         //              0.00001,0.00001);
01583         mat.SetValue(1,1,rclTrf[0][0]);
01584         mat.SetValue(2,1,rclTrf[1][0]);
01585         mat.SetValue(3,1,rclTrf[2][0]);
01586         mat.SetValue(1,2,rclTrf[0][1]);
01587         mat.SetValue(2,2,rclTrf[1][1]);
01588         mat.SetValue(3,2,rclTrf[2][1]);
01589         mat.SetValue(1,3,rclTrf[0][2]);
01590         mat.SetValue(2,3,rclTrf[1][2]);
01591         mat.SetValue(3,3,rclTrf[2][2]);
01592         mat.SetValue(1,4,rclTrf[0][3]);
01593         mat.SetValue(2,4,rclTrf[1][3]);
01594         mat.SetValue(3,4,rclTrf[2][3]);
01595     }
01596 
01597     // geometric transformation
01598     BRepBuilderAPI_GTransform mkTrf(this->_Shape, mat);
01599     return mkTrf.Shape();
01600 }
01601 
01602 void TopoShape::transformShape(const Base::Matrix4D& rclTrf)
01603 {
01604     // There is a strange behaviour of the gp_Trsf class if rclTrf has
01605     // a negative determinant.
01606     gp_Trsf mat;
01607     if (rclTrf.determinant() < 0.0) {
01608         mat.SetValues(-rclTrf[0][0],rclTrf[0][1],rclTrf[0][2],rclTrf[0][3],
01609                       -rclTrf[1][0],rclTrf[1][1],rclTrf[1][2],rclTrf[1][3],
01610                       -rclTrf[2][0],rclTrf[2][1],rclTrf[2][2],rclTrf[2][3],
01611                       0.00001,0.00001);
01612     }
01613     else {
01614         mat.SetValues(rclTrf[0][0],rclTrf[0][1],rclTrf[0][2],rclTrf[0][3],
01615                       rclTrf[1][0],rclTrf[1][1],rclTrf[1][2],rclTrf[1][3],
01616                       rclTrf[2][0],rclTrf[2][1],rclTrf[2][2],rclTrf[2][3],
01617                       0.00001,0.00001);
01618     }
01619 
01620     // location transformation
01621     BRepBuilderAPI_Transform mkTrf(this->_Shape, mat);
01622     this->_Shape = mkTrf.Shape();
01623 }
01624 
01625 TopoDS_Shape TopoShape::mirror(const gp_Ax2& ax2) const
01626 {
01627     gp_Trsf mat;
01628     mat.SetMirror(ax2);
01629     TopLoc_Location loc = this->_Shape.Location();
01630     gp_Trsf placement = loc.Transformation();
01631     mat = placement * mat;
01632     BRepBuilderAPI_Transform mkTrf(this->_Shape, mat);
01633     return mkTrf.Shape();
01634 }
01635 
01636 TopoDS_Shape TopoShape::toNurbs() const
01637 {
01638     BRepBuilderAPI_NurbsConvert mkNurbs(this->_Shape);
01639     return mkNurbs.Shape();
01640 }
01641 
01642 TopoDS_Shape TopoShape::replaceShape(const std::vector< std::pair<TopoDS_Shape,TopoDS_Shape> >& s) const
01643 {
01644     BRepTools_ReShape reshape;
01645     std::vector< std::pair<TopoDS_Shape,TopoDS_Shape> >::const_iterator it;
01646     for (it = s.begin(); it != s.end(); ++it)
01647         reshape.Replace(it->first, it->second);
01648     return reshape.Apply(this->_Shape, TopAbs_SHAPE);
01649 }
01650 
01651 TopoDS_Shape TopoShape::removeShape(const std::vector<TopoDS_Shape>& s) const
01652 {
01653     BRepTools_ReShape reshape;
01654     for (std::vector<TopoDS_Shape>::const_iterator it = s.begin(); it != s.end(); ++it)
01655         reshape.Remove(*it);
01656     return reshape.Apply(this->_Shape, TopAbs_SHAPE);
01657 }
01658 
01659 void TopoShape::sewShape()
01660 {
01661     //ShapeFix_Shape fixer(this->_Shape);
01662     //fixer.Perform();
01663     BRepBuilderAPI_Sewing sew;
01664     sew.Load(this->_Shape/*fixer.Shape()*/);
01665     sew.Perform();
01666 
01667     //shape = ShapeUpgrade_ShellSewing().ApplySewing(shape);
01668     this->_Shape = sew.SewedShape();
01669 }
01670 
01671 bool TopoShape::fix(double precision, double mintol, double maxtol)
01672 {
01673     if (this->_Shape.IsNull())
01674         return false;
01675 
01676     TopAbs_ShapeEnum type = this->_Shape.ShapeType();
01677 
01678     ShapeFix_Shape fix(this->_Shape);
01679     fix.SetPrecision(precision);
01680     fix.SetMaxTolerance(mintol);
01681     fix.SetMaxTolerance(maxtol);
01682 
01683     fix.Perform();
01684 
01685     if (type == TopAbs_SOLID) {
01686         //fix.FixEdgeTool();
01687         fix.FixWireTool()->Perform();
01688         fix.FixFaceTool()->Perform();
01689         fix.FixShellTool()->Perform();
01690         fix.FixSolidTool()->Perform();
01691         this->_Shape = fix.FixSolidTool()->Shape();
01692     }
01693     else if (type == TopAbs_SHELL) {
01694         fix.FixWireTool()->Perform();
01695         fix.FixFaceTool()->Perform();
01696         fix.FixShellTool()->Perform();
01697         this->_Shape = fix.FixShellTool()->Shape();
01698     }
01699     else if (type == TopAbs_FACE) {
01700         fix.FixWireTool()->Perform();
01701         fix.FixFaceTool()->Perform();
01702         this->_Shape = fix.Shape();
01703     }
01704     else {
01705         this->_Shape = fix.Shape();
01706     }
01707 
01708     return isValid();
01709 }
01710 
01711 bool TopoShape::removeInternalWires(double minArea)
01712 {
01713     ShapeUpgrade_RemoveInternalWires fix(this->_Shape);
01714     fix.MinArea() = minArea;
01715     bool ok = fix.Perform() ? true : false;
01716     this->_Shape = fix.GetResult();
01717     return ok;
01718 }
01719 
01720 namespace Part {
01721 struct MeshVertex
01722 {
01723     Standard_Real x,y,z;
01724     Standard_Integer i;
01725 
01726     MeshVertex(Standard_Real X, Standard_Real Y, Standard_Real Z)
01727         : x(X),y(Y),z(Z)
01728     {
01729     }
01730     MeshVertex(const gp_Pnt& p)
01731         : x(p.X()),y(p.Y()),z(p.Z())
01732     {
01733     }
01734 
01735     gp_Pnt toPoint() const
01736     { return gp_Pnt(x,y,z); }
01737 
01738     bool operator < (const MeshVertex &rclPt) const
01739     {
01740         if (fabs ( this->x - rclPt.x) >= MESH_MIN_PT_DIST)
01741             return this->x < rclPt.x;
01742         if (fabs ( this->y - rclPt.y) >= MESH_MIN_PT_DIST)
01743             return this->y < rclPt.y;
01744         if (fabs ( this->z - rclPt.z) >= MESH_MIN_PT_DIST)
01745             return this->z < rclPt.z;
01746         return false; // points are considered to be equal
01747     }
01748 
01749 private:
01750     // use the same value as used inside the Mesh module
01751     static const double MESH_MIN_PT_DIST;
01752 };
01753 }
01754 
01755 //const double Vertex::MESH_MIN_PT_DIST = 1.0e-6;
01756 const double MeshVertex::MESH_MIN_PT_DIST = gp::Resolution();
01757 
01758 #include <StlTransfer.hxx>
01759 #include <StlMesh_Mesh.hxx>
01760 #include <StlMesh_MeshExplorer.hxx>
01761 
01762 void TopoShape::getFaces(std::vector<Base::Vector3d> &aPoints,
01763                          std::vector<Facet> &aTopo,
01764                          float accuracy, uint16_t flags) const
01765 {
01766 #if 1
01767     if (this->_Shape.IsNull())
01768         return;
01769     std::set<MeshVertex> vertices;
01770     Standard_Real x1, y1, z1;
01771     Standard_Real x2, y2, z2;
01772     Standard_Real x3, y3, z3;
01773 
01774     Handle_StlMesh_Mesh aMesh = new StlMesh_Mesh();
01775     StlTransfer::BuildIncrementalMesh(this->_Shape, accuracy, aMesh);
01776     StlMesh_MeshExplorer xp(aMesh);
01777     for (Standard_Integer nbd=1;nbd<=aMesh->NbDomains();nbd++) {
01778         for (xp.InitTriangle (nbd); xp.MoreTriangle (); xp.NextTriangle ()) {
01779             xp.TriangleVertices (x1,y1,z1,x2,y2,z2,x3,y3,z3);
01780             Data::ComplexGeoData::Facet face;
01781             std::set<MeshVertex>::iterator it;
01782 
01783             // 1st vertex
01784             MeshVertex v1(x1,y1,z1);
01785             it = vertices.find(v1);
01786             if (it == vertices.end()) {
01787                 v1.i = vertices.size();
01788                 face.I1 = v1.i;
01789                 vertices.insert(v1);
01790             }
01791             else {
01792                 face.I1 = it->i;
01793             }
01794 
01795             // 2nd vertex
01796             MeshVertex v2(x2,y2,z2);
01797             it = vertices.find(v2);
01798             if (it == vertices.end()) {
01799                 v2.i = vertices.size();
01800                 face.I2 = v2.i;
01801                 vertices.insert(v2);
01802             }
01803             else {
01804                 face.I2 = it->i;
01805             }
01806 
01807             // 3rd vertex
01808             MeshVertex v3(x3,y3,z3);
01809             it = vertices.find(v3);
01810             if (it == vertices.end()) {
01811                 v3.i = vertices.size();
01812                 face.I3 = v3.i;
01813                 vertices.insert(v3);
01814             }
01815             else {
01816                 face.I3 = it->i;
01817             }
01818 
01819             // make sure that we don't insert invalid facets
01820             if (face.I1 != face.I2 &&
01821                 face.I2 != face.I3 &&
01822                 face.I3 != face.I1)
01823                 aTopo.push_back(face);
01824         }
01825     }
01826 
01827     std::vector<gp_Pnt> points;
01828     points.resize(vertices.size());
01829     for (std::set<MeshVertex>::iterator it = vertices.begin(); it != vertices.end(); ++it)
01830         points[it->i] = it->toPoint();
01831     for (std::vector<gp_Pnt>::iterator it = points.begin(); it != points.end(); ++it)
01832         aPoints.push_back(Base::Vector3d(it->X(),it->Y(),it->Z()));
01833 #endif
01834 #if 0
01835     BRepMesh::Mesh (this->_Shape, accuracy);
01836     std::set<MeshVertex> vertices;
01837     for (TopExp_Explorer xp(this->_Shape,TopAbs_FACE); xp.More(); xp.Next()) {
01838         TopoDS_Face face = TopoDS::Face(xp.Current());
01839         TopAbs_Orientation orient = face.Orientation();
01840         // change orientation of the triangles
01841         Standard_Boolean reversed = false;
01842         if (orient != TopAbs_FORWARD) {
01843             reversed = true;
01844         }
01845         TopLoc_Location aLoc;
01846         Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(face, aLoc);
01847         if (aPoly.IsNull()) continue;
01848 
01849         // getting the transformation of the shape/face
01850         gp_Trsf myTransf;
01851         Standard_Boolean identity = true;
01852         if(!aLoc.IsIdentity())  {
01853             identity = false;
01854             myTransf = aLoc.Transformation();
01855         }
01856 
01857         // cycling through the poly mesh
01858         const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
01859         for (Standard_Integer i=1;i<=Nodes.Length();i++) {
01860             Standard_Real X1, Y1, Z1;
01861             gp_Pnt p = Nodes.Value(i);
01862             p.Transform(myTransf);
01863             p.Coord (X1, Y1, Z1);
01864         }
01865 
01866         const Poly_Array1OfTriangle& Triangles = aPoly->Triangles();
01867         try {
01868             for (Standard_Integer i=1;i<=Triangles.Length();i++) {
01869                 Standard_Integer V1, V2, V3;
01870                 Poly_Triangle triangle = Triangles.Value(i);
01871                 triangle.Get(V1, V2, V3);
01872                 if (reversed)
01873                     std::swap(V1,V2);
01874                 gp_Pnt P1, P2, P3;
01875                 Data::ComplexGeoData::Facet face;
01876                 std::set<MeshVertex>::iterator it;
01877 
01878                 // 1st vertex
01879                 P1 = Nodes(V1);
01880                 P1.Transform(myTransf);
01881                 MeshVertex v1(P1);
01882                 it = vertices.find(v1);
01883                 if (it == vertices.end()) {
01884                     v1.i = vertices.size();
01885                     face.I1 = v1.i;
01886                     vertices.insert(v1);
01887                 }
01888                 else {
01889                     face.I1 = it->i;
01890                 }
01891 
01892                 // 2nd vertex
01893                 P2 = Nodes(V2);
01894                 P2.Transform(myTransf);
01895                 MeshVertex v2(P2);
01896                 it = vertices.find(v2);
01897                 if (it == vertices.end()) {
01898                     v2.i = vertices.size();
01899                     face.I2 = v2.i;
01900                     vertices.insert(v2);
01901                 }
01902                 else {
01903                     face.I2 = it->i;
01904                 }
01905                 
01906                 // 3rd vertex
01907                 P3 = Nodes(V3);
01908                 P3.Transform(myTransf);
01909                 MeshVertex v3(P3);
01910                 it = vertices.find(v3);
01911                 if (it == vertices.end()) {
01912                     v3.i = vertices.size();
01913                     face.I3 = v3.i;
01914                     vertices.insert(v3);
01915                 }
01916                 else {
01917                     face.I3 = it->i;
01918                 }
01919 
01920                 // make sure that we don't insert invalid facets
01921                 if (face.I1 != face.I2 &&
01922                     face.I2 != face.I3 &&
01923                     face.I3 != face.I1)
01924                     aTopo.push_back(face);
01925             }
01926         }
01927         catch(Standard_Failure) {
01928         }
01929     }
01930 
01931     std::map<Standard_Integer,gp_Pnt> points;
01932     for (std::set<MeshVertex>::iterator it = vertices.begin(); it != vertices.end(); ++it)
01933         points[it->i] = it->toPoint();
01934     for (std::map<Standard_Integer,gp_Pnt>::iterator it = points.begin(); it != points.end(); ++it)
01935         aPoints.push_back(Base::Vector3d(it->second.X(),it->second.Y(),it->second.Z()));
01936 #endif
01937 }
01938 
01939 void TopoShape::setFaces(const std::vector<Base::Vector3d> &Points,
01940                          const std::vector<Facet> &Topo, float Accuracy)
01941 {
01942     gp_XYZ p1, p2, p3;
01943     TopoDS_Vertex Vertex1, Vertex2, Vertex3;
01944     TopoDS_Face newFace;
01945     TopoDS_Wire newWire;
01946     BRepBuilderAPI_Sewing aSewingTool;
01947     Standard_Real x1, y1, z1;
01948     Standard_Real x2, y2, z2;
01949     Standard_Real x3, y3, z3;
01950 
01951     aSewingTool.Init(Accuracy,Standard_True);
01952 
01953     TopoDS_Compound aComp;
01954     BRep_Builder BuildTool;
01955     BuildTool.MakeCompound(aComp);
01956 
01957     unsigned int ctPoints = Points.size();
01958     for (std::vector<Facet>::const_iterator it = Topo.begin(); it != Topo.end(); ++it) {
01959         if (it->I1 >= ctPoints || it->I2 >= ctPoints || it->I3 >= ctPoints)
01960             continue;
01961         x1 = Points[it->I1].x; y1 = Points[it->I1].y; z1 = Points[it->I1].z;
01962         x2 = Points[it->I2].x; y2 = Points[it->I2].y; z2 = Points[it->I2].z;
01963         x3 = Points[it->I3].x; y3 = Points[it->I3].y; z3 = Points[it->I3].z;
01964 
01965         p1.SetCoord(x1,y1,z1);
01966         p2.SetCoord(x2,y2,z2);
01967         p3.SetCoord(x3,y3,z3);
01968 
01969         if ((!(p1.IsEqual(p2,0.0))) && (!(p1.IsEqual(p3,0.0)))) {
01970             Vertex1 = BRepBuilderAPI_MakeVertex(p1);
01971             Vertex2 = BRepBuilderAPI_MakeVertex(p2);
01972             Vertex3 = BRepBuilderAPI_MakeVertex(p3);
01973 
01974             newWire = BRepBuilderAPI_MakePolygon(Vertex1, Vertex2, Vertex3, Standard_True);
01975             if (!newWire.IsNull()) {
01976                 newFace = BRepBuilderAPI_MakeFace(newWire);
01977                 if (!newFace.IsNull())
01978                     BuildTool.Add(aComp, newFace);
01979             }
01980         }
01981     }
01982 
01983     aSewingTool.Load(aComp);
01984     aSewingTool.Perform();
01985     _Shape = aSewingTool.SewedShape();
01986     // TopAbs_Orientation o = _Shape.Orientation();
01987     _Shape.Reverse(); // seems that we have to reverse the orientation
01988     if (_Shape.IsNull())
01989         _Shape = aComp;
01990 }

Generated on Wed Nov 23 19:00:46 2011 for FreeCAD by  doxygen 1.6.1