/*************************************************************************** * Copyright (c) 2016 Victor Titov (DeepSOIC) * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include #endif #include #include "FaceMaker.h" #include "TopoShape.h" TYPESYSTEM_SOURCE_ABSTRACT(Part::FaceMaker, Base::BaseClass) TYPESYSTEM_SOURCE_ABSTRACT(Part::FaceMakerPublic, Part::FaceMaker) void Part::FaceMaker::addWire(const TopoDS_Wire& w) { this->addShape(w); } void Part::FaceMaker::addShape(const TopoDS_Shape& sh) { if(sh.IsNull()) throw Base::ValueError("Input shape is null."); switch(sh.ShapeType()){ case TopAbs_COMPOUND: this->myCompounds.push_back(TopoDS::Compound(sh)); break; case TopAbs_WIRE: this->myWires.push_back(TopoDS::Wire(sh)); break; case TopAbs_EDGE: this->myWires.push_back(BRepBuilderAPI_MakeWire(TopoDS::Edge(sh)).Wire()); break; default: throw Base::TypeError("Shape must be a wire, edge or compound. Something else was supplied."); break; } this->mySourceShapes.push_back(sh); } void Part::FaceMaker::useCompound(const TopoDS_Compound& comp) { TopoDS_Iterator it(comp); for(; it.More(); it.Next()){ this->addShape(it.Value()); } } const TopoDS_Face& Part::FaceMaker::Face() { const TopoDS_Shape &sh = this->Shape(); if(sh.IsNull()) throw NullShapeException("Part::FaceMaker: result shape is null."); if (sh.ShapeType() != TopAbs_FACE) throw Base::TypeError("Part::FaceMaker: return shape is not a single face."); return TopoDS::Face(sh); } #if OCC_VERSION_HEX >= 0x070600 void Part::FaceMaker::Build(const Message_ProgressRange&) #else void Part::FaceMaker::Build() #endif { this->NotDone(); this->myShapesToReturn.clear(); this->myGenerated.Clear(); this->Build_Essence();//adds stuff to myShapesToReturn for(const TopoDS_Compound& cmp : this->myCompounds){ std::unique_ptr facemaker = Part::FaceMaker::ConstructFromType(this->getTypeId()); facemaker->useCompound(cmp); facemaker->Build(); const TopoDS_Shape &subfaces = facemaker->Shape(); if (subfaces.IsNull()) continue; if (subfaces.ShapeType() == TopAbs_COMPOUND){ this->myShapesToReturn.push_back(subfaces); } else { //result is not a compound (probably, a face)... but we want to follow compounding structure of input, so wrap it into compound. TopoDS_Builder builder; TopoDS_Compound cmp_res; builder.MakeCompound(cmp_res); builder.Add(cmp_res,subfaces); this->myShapesToReturn.push_back(cmp_res); } } if(this->myShapesToReturn.empty()){ //nothing to do, null shape will be returned. } else if (this->myShapesToReturn.size() == 1){ this->myShape = this->myShapesToReturn[0]; } else { TopoDS_Builder builder; TopoDS_Compound cmp_res; builder.MakeCompound(cmp_res); for(TopoDS_Shape &sh: this->myShapesToReturn){ builder.Add(cmp_res,sh); } this->myShape = cmp_res; } this->Done(); } std::unique_ptr Part::FaceMaker::ConstructFromType(const char* className) { Base::Type fmType = Base::Type::fromName(className); if (fmType.isBad()){ std::stringstream ss; ss << "Class '"<< className <<"' not found."; throw Base::TypeError(ss.str().c_str()); } return Part::FaceMaker::ConstructFromType(fmType); } std::unique_ptr Part::FaceMaker::ConstructFromType(Base::Type type) { if (!type.isDerivedFrom(Part::FaceMaker::getClassTypeId())){ std::stringstream ss; ss << "Class '" << type.getName() << "' is not derived from Part::FaceMaker."; throw Base::TypeError(ss.str().c_str()); } std::unique_ptr instance(static_cast(type.createInstance())); if (!instance){ std::stringstream ss; ss << "Cannot create FaceMaker from abstract type '" << type.getName() << "'"; throw Base::TypeError(ss.str().c_str()); } return instance; } void Part::FaceMaker::throwNotImplemented() { throw Base::NotImplementedError("Not implemented yet..."); } //---------------------------------------------------------------------------------------- TYPESYSTEM_SOURCE(Part::FaceMakerSimple, Part::FaceMakerPublic) std::string Part::FaceMakerSimple::getUserFriendlyName() const { return std::string(QT_TRANSLATE_NOOP("Part_FaceMaker","Simple")); } std::string Part::FaceMakerSimple::getBriefExplanation() const { return std::string(QT_TRANSLATE_NOOP("Part_FaceMaker","Makes separate plane face from every wire independently. No support for holes; wires can be on different planes.")); } void Part::FaceMakerSimple::Build_Essence() { for(TopoDS_Wire &w: myWires){ this->myShapesToReturn.push_back(BRepBuilderAPI_MakeFace(w).Shape()); } }