Part: Introduce FaceMaker class
A general class to implement smart making faces from wires (e.g. making a face from sketch prior to extruding)
This commit is contained in:
parent
ec624b91d7
commit
b6db15a5d3
|
@ -282,6 +282,8 @@ SET(Part_SRCS
|
|||
OCCError.h
|
||||
FT2FC.cpp
|
||||
FT2FC.h
|
||||
FaceMaker.cpp
|
||||
FaceMaker.h
|
||||
)
|
||||
|
||||
SET(Part_Scripts
|
||||
|
|
180
src/Mod/Part/App/FaceMaker.cpp
Normal file
180
src/Mod/Part/App/FaceMaker.cpp
Normal file
|
@ -0,0 +1,180 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
|
||||
* *
|
||||
* 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 <TopoDS.hxx>
|
||||
# include <TopoDS_Iterator.hxx>
|
||||
# include <BRep_Builder.hxx>
|
||||
# include <BRepBuilderAPI_MakeWire.hxx>
|
||||
# include <BRepBuilderAPI_MakeFace.hxx>
|
||||
# include <BRep_Tool.hxx>
|
||||
#endif
|
||||
|
||||
#include "FaceMaker.h"
|
||||
|
||||
#include <Base/Exception.h>
|
||||
#include <memory>
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
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 Base::Exception("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);
|
||||
}
|
||||
|
||||
void Part::FaceMaker::Build()
|
||||
{
|
||||
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> facemaker_instance = Part::FaceMaker::ConstructFromType(this->getTypeId());
|
||||
FaceMaker* facemaker = &(*facemaker_instance); //handy to have plain pointer for intellisense to work =)
|
||||
|
||||
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> 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::Exception(ss.str().c_str());
|
||||
}
|
||||
return Part::FaceMaker::ConstructFromType(fmType);
|
||||
}
|
||||
|
||||
std::unique_ptr<Part::FaceMaker> 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());
|
||||
}
|
||||
return std::unique_ptr<FaceMaker>(static_cast<Part::FaceMaker*>(type.createInstance()));
|
||||
}
|
||||
|
||||
void Part::FaceMaker::throwNotImplemented()
|
||||
{
|
||||
throw Base::NotImplementedError("Not implemente 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());
|
||||
}
|
||||
}
|
145
src/Mod/Part/App/FaceMaker.h
Normal file
145
src/Mod/Part/App/FaceMaker.h
Normal file
|
@ -0,0 +1,145 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016 Victor Titov (DeepSOIC) <vv.titov@gmail.com> *
|
||||
* *
|
||||
* 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 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PART_FACEMAKER_H
|
||||
#define PART_FACEMAKER_H
|
||||
|
||||
#include <BRepBuilderAPI_MakeShape.hxx>
|
||||
#include <Base/BaseClass.h>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Part
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief FaceMaker class is the base class for implementing various "smart"
|
||||
* face making routines. This was created to address the problem of multiple
|
||||
* private implementations of making faces with holes, which are quite complex.
|
||||
* The two most important facemaking routines then was: one in Part Extrude,
|
||||
* and one in PartDesign (there, it is used in every sketch-based feature).
|
||||
* Plus, another one (new) was needed for filling 2D offset.
|
||||
*/
|
||||
class PartExport FaceMaker: public BRepBuilderAPI_MakeShape, public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
FaceMaker() {};
|
||||
virtual ~FaceMaker() {};
|
||||
|
||||
virtual void addWire(const TopoDS_Wire& w);
|
||||
/**
|
||||
* @brief addShape: add another wire, edge, or compound. If compound is
|
||||
* added, its internals will be treated as isolated from the rest, and the
|
||||
* compounding structure of result will follow.
|
||||
* @param sh
|
||||
*/
|
||||
virtual void addShape(const TopoDS_Shape& sh);
|
||||
/**
|
||||
* @brief useCompound: add children of compound to the FaceMaker. Note that
|
||||
* this is different from addShape(comp) - structure is lost. The compound
|
||||
* is NOT expanded recursively.
|
||||
* @param comp
|
||||
*/
|
||||
virtual void useCompound(const TopoDS_Compound &comp);
|
||||
|
||||
/**
|
||||
* @brief Face: returns the face (result). If result is not a single face,
|
||||
* throws Base::TypeError. (hint: use .Shape() instead)
|
||||
* @return
|
||||
*/
|
||||
virtual const TopoDS_Face& Face();
|
||||
|
||||
virtual void Build();
|
||||
|
||||
//fails to compile, huh!
|
||||
//virtual const TopTools_ListOfShape& Generated(const TopoDS_Shape &S) override {throwNotImplemented();}
|
||||
//virtual const TopTools_ListOfShape& Modified(const TopoDS_Shape &S) override {throwNotImplemented();}
|
||||
//virtual Standard_Boolean IsDeleted(const TopoDS_Shape &S) override {throwNotImplemented();}
|
||||
|
||||
static std::unique_ptr<FaceMaker> ConstructFromType(const char* className);
|
||||
static std::unique_ptr<FaceMaker> ConstructFromType(Base::Type type);
|
||||
|
||||
protected:
|
||||
std::vector<TopoDS_Shape> mySourceShapes; //wire or compound
|
||||
std::vector<TopoDS_Wire> myWires; //wires from mySourceShapes
|
||||
std::vector<TopoDS_Compound> myCompounds; //compounds, for recursive processing
|
||||
std::vector<TopoDS_Shape> myShapesToReturn;
|
||||
|
||||
/**
|
||||
* @brief Build_Essence: build routine that can assume there is no nesting.
|
||||
*
|
||||
* Implementing instructions:
|
||||
* Add new faces (or whatever) to myShapesToReturn. The rest is done by
|
||||
* base class's Build(). Please ignore contents of myCompounds in
|
||||
* implementation. If special handling of nesting is required, override
|
||||
* whole Build().
|
||||
*/
|
||||
virtual void Build_Essence() = 0;
|
||||
|
||||
static void throwNotImplemented();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The FaceMakerPublic class: derive from it if you want the face maker to be listed in tools that allow choosing one.
|
||||
*/
|
||||
class PartExport FaceMakerPublic : public FaceMaker
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
public:
|
||||
virtual std::string getUserFriendlyName() const = 0;
|
||||
virtual std::string getBriefExplanation() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The FaceMakerSimple class: make plane faces from all closed wires
|
||||
* supplied, ignoring overlaps.
|
||||
*
|
||||
* Strengths: can work with non-coplanar sets of wires. Will not make broken
|
||||
* faces if wires overlap*.
|
||||
*
|
||||
* Limitations: can't make faces with holes (will generate overlapping faces
|
||||
* instead). Can't make faces from nonplanar wires.
|
||||
*
|
||||
* * Compound of valid but overlapping faces is created. The compound is invalid
|
||||
* for BOPs, but the faces themselves are valid, provided that the source wires
|
||||
* are valid.
|
||||
*/
|
||||
class PartExport FaceMakerSimple : public FaceMakerPublic
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
public:
|
||||
virtual std::string getUserFriendlyName() const override;
|
||||
virtual std::string getBriefExplanation() const override;
|
||||
protected:
|
||||
virtual void Build_Essence() override;
|
||||
};
|
||||
|
||||
|
||||
}//namespace Part
|
||||
#endif // PART_FACEMAKER_H
|
Loading…
Reference in New Issue
Block a user