FeatureFace.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <Bnd_Box.hxx>
00027 # include <gp_Pln.hxx>
00028 # include <BRep_Builder.hxx>
00029 # include <BRepBndLib.hxx>
00030 # include <BRepBuilderAPI_Copy.hxx>
00031 # include <BRepBuilderAPI_MakeFace.hxx>
00032 # include <BRepAdaptor_Surface.hxx>
00033 # include <Geom_Plane.hxx>
00034 # include <Handle_Geom_Surface.hxx>
00035 # include <TopoDS.hxx>
00036 # include <TopoDS_Compound.hxx>
00037 # include <TopoDS_Face.hxx>
00038 # include <TopoDS_Wire.hxx>
00039 # include <TopExp_Explorer.hxx>
00040 # include <BRepAlgoAPI_Fuse.hxx>
00041 # include <gp_Pln.hxx>
00042 #endif
00043
00044 #include <Base/Placement.h>
00045 #include <Mod/Part/App/Part2DObject.h>
00046
00047 #include "FeatureFace.h"
00048
00049
00050 using namespace PartDesign;
00051
00052
00053 PROPERTY_SOURCE(PartDesign::Face, Part::Part2DObject)
00054
00055 Face::Face()
00056 {
00057 ADD_PROPERTY(Sources,(0));
00058 Sources.setSize(0);
00059 }
00060
00061 short Face::mustExecute() const
00062 {
00063 if (Sources.isTouched())
00064 return 1;
00065 return 0;
00066 }
00067
00068 App::DocumentObjectExecReturn *Face::execute(void)
00069 {
00070 std::vector<App::DocumentObject*> links = Sources.getValues();
00071 if (links.empty())
00072 return new App::DocumentObjectExecReturn("No shapes linked");
00073
00074 std::vector<TopoDS_Wire> wires;
00075 for (std::vector<App::DocumentObject*>::iterator it = links.begin(); it != links.end(); ++it) {
00076 if (!(*it && (*it)->isDerivedFrom(Part::Part2DObject::getClassTypeId())))
00077 return new App::DocumentObjectExecReturn("Linked object is not a Sketch or Part2DObject");
00078 TopoDS_Shape shape = static_cast<Part::Part2DObject*>(*it)->Shape.getShape()._Shape;
00079 if (shape.IsNull())
00080 return new App::DocumentObjectExecReturn("Linked shape object is empty");
00081
00082
00083
00084
00085 if (!this->Shape.getValue().IsNull()) {
00086 BRepBuilderAPI_Copy copy(shape);
00087 shape = copy.Shape();
00088 if (shape.IsNull())
00089 return new App::DocumentObjectExecReturn("Linked shape object is empty");
00090 }
00091
00092 TopExp_Explorer ex;
00093 for (ex.Init(shape, TopAbs_WIRE); ex.More(); ex.Next()) {
00094 wires.push_back(TopoDS::Wire(ex.Current()));
00095 }
00096 }
00097
00098 if (wires.empty())
00099 return new App::DocumentObjectExecReturn("Linked shape object is not a wire");
00100
00101 TopoDS_Shape aFace = makeFace(wires);
00102 if (aFace.IsNull())
00103 return new App::DocumentObjectExecReturn("Creating a face from sketch failed");
00104 this->Shape.setValue(aFace);
00105
00106 return App::DocumentObject::StdReturn;
00107 }
00108
00109 namespace PartDesign {
00110
00111
00112 struct Wire_Compare {
00113 bool operator() (const TopoDS_Wire& w1, const TopoDS_Wire& w2)
00114 {
00115 Bnd_Box box1, box2;
00116 BRepBndLib::Add(w1, box1);
00117 box1.SetGap(0.0);
00118
00119 BRepBndLib::Add(w2, box2);
00120 box2.SetGap(0.0);
00121
00122 return box1.SquareExtent() < box2.SquareExtent();
00123 }
00124 };
00125 }
00126
00127 TopoDS_Shape Face::makeFace(std::list<TopoDS_Wire>& wires) const
00128 {
00129 BRepBuilderAPI_MakeFace mkFace(wires.front());
00130 const TopoDS_Face& face = mkFace.Face();
00131 if (face.IsNull())
00132 return face;
00133 gp_Dir axis(0,0,1);
00134 BRepAdaptor_Surface adapt(face);
00135 if (adapt.GetType() == GeomAbs_Plane) {
00136 axis = adapt.Plane().Axis().Direction();
00137 }
00138
00139 wires.pop_front();
00140 for (std::list<TopoDS_Wire>::iterator it = wires.begin(); it != wires.end(); ++it) {
00141 BRepBuilderAPI_MakeFace mkInnerFace(*it);
00142 const TopoDS_Face& inner_face = mkInnerFace.Face();
00143 gp_Dir inner_axis(0,0,1);
00144 BRepAdaptor_Surface adapt(inner_face);
00145 if (adapt.GetType() == GeomAbs_Plane) {
00146 inner_axis = adapt.Plane().Axis().Direction();
00147 }
00148
00149
00150 if (axis.Dot(inner_axis) < 0)
00151 it->Reverse();
00152 mkFace.Add(*it);
00153 }
00154 return mkFace.Face();
00155 }
00156
00157 TopoDS_Shape Face::makeFace(const std::vector<TopoDS_Wire>& w) const
00158 {
00159 if (w.empty())
00160 return TopoDS_Shape();
00161
00162
00163
00164 std::vector<TopoDS_Wire> wires = w;
00165 std::sort(wires.begin(), wires.end(), Wire_Compare());
00166 std::list<TopoDS_Wire> wire_list;
00167 wire_list.insert(wire_list.begin(), wires.rbegin(), wires.rend());
00168
00169
00170 std::list< std::list<TopoDS_Wire> > sep_wire_list;
00171 while (!wire_list.empty()) {
00172 std::list<TopoDS_Wire> sep_list;
00173 TopoDS_Wire wire = wire_list.front();
00174 wire_list.pop_front();
00175 sep_list.push_back(wire);
00176
00177 Bnd_Box box;
00178 BRepBndLib::Add(wire, box);
00179 box.SetGap(0.0);
00180
00181 std::list<TopoDS_Wire>::iterator it = wire_list.begin();
00182 while (it != wire_list.end()) {
00183 Bnd_Box box2;
00184 BRepBndLib::Add(*it, box2);
00185 box2.SetGap(0.0);
00186 if (!box.IsOut(box2)) {
00187 sep_list.push_back(*it);
00188 it = wire_list.erase(it);
00189 }
00190 else {
00191 ++it;
00192 }
00193 }
00194
00195 sep_wire_list.push_back(sep_list);
00196 }
00197
00198 if (sep_wire_list.size() == 1) {
00199 std::list<TopoDS_Wire>& wires = sep_wire_list.front();
00200 return makeFace(wires);
00201 }
00202 else if (sep_wire_list.size() > 1) {
00203 TopoDS_Compound comp;
00204 BRep_Builder builder;
00205 builder.MakeCompound(comp);
00206 for (std::list< std::list<TopoDS_Wire> >::iterator it = sep_wire_list.begin(); it != sep_wire_list.end(); ++it) {
00207 TopoDS_Shape aFace = makeFace(*it);
00208 if (!aFace.IsNull())
00209 builder.Add(comp, aFace);
00210 }
00211
00212 return comp;
00213 }
00214 else {
00215 return TopoDS_Shape();
00216 }
00217 }
00218