Format code with clang-format

This commit is contained in:
André Althaus
2024-05-23 12:23:28 +02:00
parent 98d46c41be
commit 75bba376c4
6 changed files with 297 additions and 221 deletions

View File

@@ -23,9 +23,9 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <BRepGProp.hxx>
# include <GProp_GProps.hxx>
# include <Precision.hxx>
#include <BRepGProp.hxx>
#include <GProp_GProps.hxx>
#include <Precision.hxx>
#endif
#include "FeatureMultiTransform.h"
@@ -35,14 +35,15 @@
using namespace PartDesign;
namespace PartDesign {
namespace PartDesign
{
PROPERTY_SOURCE(PartDesign::MultiTransform, PartDesign::Transformed)
MultiTransform::MultiTransform()
{
ADD_PROPERTY(Transformations,(nullptr));
ADD_PROPERTY(Transformations, (nullptr));
Transformations.setSize(0);
}
@@ -51,8 +52,9 @@ void MultiTransform::positionBySupport()
PartDesign::Transformed::positionBySupport();
std::vector<App::DocumentObject*> transFeatures = Transformations.getValues();
for (auto f : transFeatures) {
if (!(f->isDerivedFrom<PartDesign::Transformed>()))
if (!(f->isDerivedFrom<PartDesign::Transformed>())) {
throw Base::TypeError("Transformation features must be subclasses of Transformed");
}
PartDesign::Transformed* transFeature = static_cast<PartDesign::Transformed*>(f);
transFeature->Placement.setValue(this->Placement.getValue());
@@ -66,27 +68,29 @@ void MultiTransform::positionBySupport()
short MultiTransform::mustExecute() const
{
if (Transformations.isTouched())
if (Transformations.isTouched()) {
return 1;
}
return Transformed::mustExecute();
}
const std::list<gp_Trsf> MultiTransform::getTransformations(const std::vector<App::DocumentObject*> originals)
const std::list<gp_Trsf>
MultiTransform::getTransformations(const std::vector<App::DocumentObject*> originals)
{
std::vector<App::DocumentObject*> transFeatures = Transformations.getValues();
gp_Pnt cog;
if (!originals.empty()) {
// Find centre of gravity of first original
// FIXME: This method will NOT give the expected result for more than one original!
if (auto addFeature =
Base::freecad_dynamic_cast<PartDesign::FeatureAddSub>(originals.front())) {
TopoDS_Shape original = addFeature->AddSubShape.getShape().getShape();
// Find centre of gravity of first original
// FIXME: This method will NOT give the expected result for more than one original!
if (auto addFeature =
Base::freecad_dynamic_cast<PartDesign::FeatureAddSub>(originals.front())) {
TopoDS_Shape original = addFeature->AddSubShape.getShape().getShape();
GProp_GProps props;
BRepGProp::VolumeProperties(original, props);
cog = props.CentreOfMass();
}
GProp_GProps props;
BRepGProp::VolumeProperties(original, props);
cog = props.CentreOfMass();
}
}
std::list<gp_Trsf> result;
@@ -94,24 +98,28 @@ const std::list<gp_Trsf> MultiTransform::getTransformations(const std::vector<Ap
std::vector<App::DocumentObject*>::const_iterator f;
for (f = transFeatures.begin(); f != transFeatures.end(); ++f) {
if (!((*f)->isDerivedFrom<PartDesign::Transformed>()))
if (!((*f)->isDerivedFrom<PartDesign::Transformed>())) {
throw Base::TypeError("Transformation features must be subclasses of Transformed");
}
PartDesign::Transformed* transFeature = static_cast<PartDesign::Transformed*>(*f);
std::list<gp_Trsf> newTransformations = transFeature->getTransformations(originals);
if (result.empty()) {
// First transformation Feature
result = newTransformations;
for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) {
for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin();
nt != newTransformations.end();
++nt) {
cogs.push_back(cog.Transformed(*nt));
}
} else {
}
else {
// Retain a copy of the first set of transformations for iterator ot
// We can't iterate through result if we are also adding elements with push_back()!
std::list<gp_Trsf> oldTransformations;
result.swap(oldTransformations); // empty result to receive new transformations
result.swap(oldTransformations); // empty result to receive new transformations
std::list<gp_Pnt> oldCogs;
cogs.swap(oldCogs); // empty cogs to receive new cogs
cogs.swap(oldCogs); // empty cogs to receive new cogs
if ((*f)->is<PartDesign::Scaled>()) {
// Diagonal method
@@ -123,25 +131,33 @@ const std::list<gp_Trsf> MultiTransform::getTransformations(const std::vector<Ap
// In other words, the length of the result vector is equal to the length of the
// oldTransformations vector
if (newTransformations.empty())
throw Base::ValueError("Number of occurrences must be a divisor of previous number of occurrences");
if (oldTransformations.size() % newTransformations.size() != 0)
throw Base::ValueError("Number of occurrences must be a divisor of previous number of occurrences");
if (newTransformations.empty()) {
throw Base::ValueError("Number of occurrences must be a divisor of previous "
"number of occurrences");
}
if (oldTransformations.size() % newTransformations.size() != 0) {
throw Base::ValueError("Number of occurrences must be a divisor of previous "
"number of occurrences");
}
unsigned sliceLength = oldTransformations.size() / newTransformations.size();
std::list<gp_Trsf>::const_iterator ot = oldTransformations.begin();
std::list<gp_Pnt>::const_iterator oc = oldCogs.begin();
for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) {
for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin();
nt != newTransformations.end();
++nt) {
for (unsigned s = 0; s < sliceLength; s++) {
gp_Trsf trans;
double factor = nt->ScaleFactor(); // extract scale factor
double factor = nt->ScaleFactor(); // extract scale factor
if (factor > Precision::Confusion()) {
trans.SetScale(*oc, factor); // recreate the scaled transformation to use the correct COG
trans.SetScale(*oc, factor); // recreate the scaled transformation to
// use the correct COG
trans = trans * (*ot);
cogs.push_back(*oc); // Scaling does not affect the COG
} else {
cogs.push_back(*oc); // Scaling does not affect the COG
}
else {
trans = (*nt) * (*ot);
cogs.push_back(oc->Transformed(*nt));
}
@@ -150,30 +166,35 @@ const std::list<gp_Trsf> MultiTransform::getTransformations(const std::vector<Ap
++oc;
}
}
} else {
}
else {
// Multiplication method: Combine the new transformations with the old ones.
// All old transformations are multiplied with all new ones, so that the length of the
// result vector is the length of the old and new transformations multiplied.
// All old transformations are multiplied with all new ones, so that the length of
// the result vector is the length of the old and new transformations multiplied.
// a11 a12 b1 a11*b1 a12*b1 a11*b2 a12*b2 a11*b3 a12*b3
// a21 a22 mul b2 = a21*b1 a22*b1 a21*b2 a22*b2 a21*b3 a22*b3
// b3
for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) {
for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin();
nt != newTransformations.end();
++nt) {
std::list<gp_Pnt>::const_iterator oc = oldCogs.begin();
for (std::list<gp_Trsf>::const_iterator ot = oldTransformations.begin(); ot != oldTransformations.end(); ++ot) {
for (std::list<gp_Trsf>::const_iterator ot = oldTransformations.begin();
ot != oldTransformations.end();
++ot) {
result.push_back((*nt) * (*ot));
cogs.push_back(oc->Transformed(*nt));
++oc;
}
}
}
// What about the Additive method: Take the last (set of) transformations and use them as
// "originals" for the next transformationFeature, so that something similar to a sweep
// for transformations could be put together?
// What about the Additive method: Take the last (set of) transformations and use them
// as "originals" for the next transformationFeature, so that something similar to a
// sweep for transformations could be put together?
}
}
return result;
}
}
} // namespace PartDesign

View File

@@ -30,7 +30,7 @@
namespace PartDesign
{
class PartDesignExport MultiTransform : public PartDesign::Transformed
class PartDesignExport MultiTransform: public PartDesign::Transformed
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesign::MultiTransform);
@@ -39,30 +39,35 @@ public:
App::PropertyLinkList Transformations;
/** @name methods override feature */
/** @name methods override feature */
//@{
short mustExecute() const override;
/// returns the type name of the view provider
const char* getViewProviderName() const override {
const char* getViewProviderName() const override
{
return "PartDesignGui::ViewProviderMultiTransform";
}
//@}
std::vector<App::DocumentObject*> getOriginals() const { return Originals.getValues(); }
std::vector<App::DocumentObject*> getOriginals() const
{
return Originals.getValues();
}
/** Create transformations
* Returns a list containing the product of all transformations of the subfeatures given
* by the Transformations property. Subfeatures can be Mirrored, LinearPattern, PolarPattern and
* Scaled.
*/
const std::list<gp_Trsf> getTransformations(const std::vector<App::DocumentObject*> originals) override;
* Returns a list containing the product of all transformations of the subfeatures given
* by the Transformations property. Subfeatures can be Mirrored, LinearPattern, PolarPattern and
* Scaled.
*/
const std::list<gp_Trsf>
getTransformations(const std::vector<App::DocumentObject*> originals) override;
protected:
void positionBySupport() override;
};
} //namespace PartDesign
} // namespace PartDesign
#endif // PARTDESIGN_FeatureMultiTransform_H
#endif // PARTDESIGN_FeatureMultiTransform_H

View File

@@ -23,9 +23,9 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <BRepGProp.hxx>
# include <GProp_GProps.hxx>
# include <Precision.hxx>
#include <BRepGProp.hxx>
#include <GProp_GProps.hxx>
#include <Precision.hxx>
#endif
#include "FeatureScaled.h"
@@ -34,33 +34,37 @@
using namespace PartDesign;
namespace PartDesign {
namespace PartDesign
{
PROPERTY_SOURCE(PartDesign::Scaled, PartDesign::Transformed)
Scaled::Scaled()
{
ADD_PROPERTY(Factor,(2.0));
ADD_PROPERTY(Occurrences,(2));
ADD_PROPERTY(Factor, (2.0));
ADD_PROPERTY(Occurrences, (2));
}
short Scaled::mustExecute() const
{
if (Factor.isTouched() ||
Occurrences.isTouched())
if (Factor.isTouched() || Occurrences.isTouched()) {
return 1;
}
return Transformed::mustExecute();
}
const std::list<gp_Trsf> Scaled::getTransformations(const std::vector<App::DocumentObject*> originals)
const std::list<gp_Trsf>
Scaled::getTransformations(const std::vector<App::DocumentObject*> originals)
{
double factor = Factor.getValue();
if (factor < Precision::Confusion())
if (factor < Precision::Confusion()) {
throw Base::ValueError("Scaling factor too small");
}
int occurrences = Occurrences.getValue();
if (occurrences < 2)
if (occurrences < 2) {
throw Base::ValueError("At least two occurrences required");
}
double f = (factor - 1.0) / double(occurrences - 1);
@@ -81,7 +85,7 @@ const std::list<gp_Trsf> Scaled::getTransformations(const std::vector<App::Docum
// we start with occurrence number 1, not number 0
std::list<gp_Trsf> transformations;
gp_Trsf trans;
transformations.push_back(trans); // identity transformation
transformations.push_back(trans); // identity transformation
for (int i = 1; i < occurrences; i++) {
trans.SetScale(cog, 1.0 + double(i) * f);
@@ -91,4 +95,4 @@ const std::list<gp_Trsf> Scaled::getTransformations(const std::vector<App::Docum
return transformations;
}
}
} // namespace PartDesign

View File

@@ -31,39 +31,41 @@
namespace PartDesign
{
class PartDesignExport Scaled : public PartDesign::Transformed
class PartDesignExport Scaled: public PartDesign::Transformed
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesign::Scaled);
public:
Scaled();
App::PropertyFloat Factor;
App::PropertyFloat Factor;
App::PropertyInteger Occurrences;
/** @name methods override feature */
/** @name methods override feature */
//@{
short mustExecute() const override;
/// returns the type name of the view provider
const char* getViewProviderName() const override {
const char* getViewProviderName() const override
{
return "PartDesignGui::ViewProviderScaled";
}
//@}
/** Create transformations
* Returns a list containing (Occurrences-1) transformation since the first, untransformed instance
* is not counted. Each transformation will scale the shape it is applied to by the factor
* (Factor / (Occurrences - 1))
* The centre point of the scaling (currently) is the centre of gravity of the first original shape
* for this reason we need to pass the list of originals into the feature
*/
* Returns a list containing (Occurrences-1) transformation since the first, untransformed
* instance is not counted. Each transformation will scale the shape it is applied to by the
* factor (Factor / (Occurrences - 1)) The centre point of the scaling (currently) is the centre
* of gravity of the first original shape for this reason we need to pass the list of originals
* into the feature
*/
// Note: We can't just use the Originals property because this will fail if the Scaled feature
// is being used inside a MultiTransform feature
const std::list<gp_Trsf> getTransformations(const std::vector<App::DocumentObject*> originals) override;
const std::list<gp_Trsf>
getTransformations(const std::vector<App::DocumentObject*> originals) override;
};
} //namespace PartDesign
} // namespace PartDesign
#endif // PARTDESIGN_FeatureScaled_H
#endif // PARTDESIGN_FeatureScaled_H

View File

@@ -22,15 +22,15 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Bnd_Box.hxx>
# include <BRep_Builder.hxx>
# include <BRepAlgoAPI_Cut.hxx>
# include <BRepAlgoAPI_Fuse.hxx>
# include <BRepBndLib.hxx>
# include <BRepBuilderAPI_Copy.hxx>
# include <BRepBuilderAPI_Transform.hxx>
# include <Precision.hxx>
# include <TopExp_Explorer.hxx>
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <Precision.hxx>
#include <TopExp_Explorer.hxx>
#endif
#include <array>
@@ -54,7 +54,8 @@
using namespace PartDesign;
namespace PartDesign {
namespace PartDesign
{
PROPERTY_SOURCE(PartDesign::Transformed, PartDesign::Feature)
@@ -64,46 +65,59 @@ std::array<char const*, 3> transformModeEnums = {"Transform tool shapes",
Transformed::Transformed()
{
ADD_PROPERTY(Originals,(nullptr));
ADD_PROPERTY(Originals, (nullptr));
Originals.setSize(0);
Placement.setStatus(App::Property::ReadOnly, true);
ADD_PROPERTY(TransformMode, (static_cast<int>(Mode::TransformToolShapes)));
TransformMode.setEnums(transformModeEnums.data());
ADD_PROPERTY_TYPE(Refine,(0),"Part Design",(App::PropertyType)(App::Prop_None),"Refine shape (clean up redundant edges) after adding/subtracting");
ADD_PROPERTY_TYPE(Refine,
(0),
"Part Design",
(App::PropertyType)(App::Prop_None),
"Refine shape (clean up redundant edges) after adding/subtracting");
//init Refine property
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/PartDesign");
// init Refine property
Base::Reference<ParameterGrp> hGrp = App::GetApplication()
.GetUserParameter()
.GetGroup("BaseApp")
->GetGroup("Preferences")
->GetGroup("Mod/PartDesign");
this->Refine.setValue(hGrp->GetBool("RefineModel", false));
}
void Transformed::positionBySupport()
{
// TODO May be here better to throw exception (silent=false) (2015-07-27, Fat-Zer)
Part::Feature *support = getBaseObject(/* silent =*/ true);
if (support)
Part::Feature* support = getBaseObject(/* silent =*/true);
if (support) {
this->Placement.setValue(support->Placement.getValue());
}
}
Part::Feature* Transformed::getBaseObject(bool silent) const {
Part::Feature *rv = Feature::getBaseObject(/* silent = */ true);
Part::Feature* Transformed::getBaseObject(bool silent) const
{
Part::Feature* rv = Feature::getBaseObject(/* silent = */ true);
if (rv) {
return rv;
}
const char* err = nullptr;
const std::vector<App::DocumentObject*> & originals = Originals.getValues();
// NOTE: may be here supposed to be last origin but in order to keep the old behaviour keep here first
const std::vector<App::DocumentObject*>& originals = Originals.getValues();
// NOTE: may be here supposed to be last origin but in order to keep the old behaviour keep here
// first
App::DocumentObject* firstOriginal = originals.empty() ? nullptr : originals.front();
if (firstOriginal) {
if(firstOriginal->isDerivedFrom(Part::Feature::getClassTypeId())) {
if (firstOriginal->isDerivedFrom(Part::Feature::getClassTypeId())) {
rv = static_cast<Part::Feature*>(firstOriginal);
} else {
err = QT_TRANSLATE_NOOP("Exception", "Transformation feature Linked object is not a Part object");
}
} else {
else {
err = QT_TRANSLATE_NOOP("Exception",
"Transformation feature Linked object is not a Part object");
}
}
else {
err = QT_TRANSLATE_NOOP("Exception", "No originals linked to the transformed feature.");
}
@@ -143,7 +157,7 @@ App::DocumentObject* Transformed::getSketchObject() const
}
}
void Transformed::Restore(Base::XMLReader &reader)
void Transformed::Restore(Base::XMLReader& reader)
{
PartDesign::Feature::Restore(reader);
}
@@ -164,13 +178,15 @@ bool Transformed::isMultiTransformChild() const
return false;
}
void Transformed::handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, App::Property * prop)
void Transformed::handleChangedPropertyType(Base::XMLReader& reader,
const char* TypeName,
App::Property* prop)
{
// The property 'Angle' of PolarPattern has changed from PropertyFloat
// to PropertyAngle and the property 'Length' has changed to PropertyLength.
Base::Type inputType = Base::Type::fromName(TypeName);
if (prop->isDerivedFrom<App::PropertyFloat>() &&
inputType.isDerivedFrom(App::PropertyFloat::getClassTypeId())) {
if (prop->isDerivedFrom<App::PropertyFloat>()
&& inputType.isDerivedFrom(App::PropertyFloat::getClassTypeId())) {
// Do not directly call the property's Restore method in case the implementation
// has changed. So, create a temporary PropertyFloat object and assign the value.
App::PropertyFloat floatProp;
@@ -190,7 +206,7 @@ short Transformed::mustExecute() const
return PartDesign::Feature::mustExecute();
}
App::DocumentObjectExecReturn *Transformed::execute()
App::DocumentObjectExecReturn* Transformed::execute()
{
if (isMultiTransformChild()) {
return App::DocumentObject::StdReturn;
@@ -201,9 +217,9 @@ App::DocumentObjectExecReturn *Transformed::execute()
Originals.setValues({});
}
if(!this->BaseFeature.getValue()) {
if (!this->BaseFeature.getValue()) {
auto body = getFeatureBody();
if(body) {
if (body) {
body->setBaseProperty(this);
}
}
@@ -211,12 +227,14 @@ App::DocumentObjectExecReturn *Transformed::execute()
this->positionBySupport();
std::vector<App::DocumentObject*> originals = Originals.getValues();
// Remove suppressed features from the list so the transformations behave as if they are not there
// Remove suppressed features from the list so the transformations behave as if they are not
// there
{
auto eraseIter = std::remove_if(originals.begin(), originals.end(), [](App::DocumentObject const* obj) {
auto feature = Base::freecad_dynamic_cast<PartDesign::Feature>(obj);
return feature != nullptr && feature->Suppressed.getValue();
});
auto eraseIter =
std::remove_if(originals.begin(), originals.end(), [](App::DocumentObject const* obj) {
auto feature = Base::freecad_dynamic_cast<PartDesign::Feature>(obj);
return feature != nullptr && feature->Suppressed.getValue();
});
originals.erase(eraseIter, originals.end());
}
@@ -237,21 +255,25 @@ App::DocumentObjectExecReturn *Transformed::execute()
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
if (transformations.empty())
return App::DocumentObject::StdReturn; // No transformations defined, exit silently
if (transformations.empty()) {
return App::DocumentObject::StdReturn; // No transformations defined, exit silently
}
// Get the support
Part::Feature* supportFeature;
try {
supportFeature = getBaseObject();
} catch (Base::Exception& e) {
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
const Part::TopoShape& supportTopShape = supportFeature->Shape.getShape();
if (supportTopShape.getShape().IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Cannot transform invalid support shape"));
if (supportTopShape.getShape().IsNull()) {
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "Cannot transform invalid support shape"));
}
// create an untransformed copy of the support shape
Part::TopoShape supportShape(supportTopShape);
@@ -261,8 +283,7 @@ App::DocumentObjectExecReturn *Transformed::execute()
supportShape.setTransform(Base::Matrix4D());
TopoDS_Shape support = supportShape.getShape();
auto getTransformedCompShape = [&](const auto& origShape)
{
auto getTransformedCompShape = [&](const auto& origShape) {
TopTools_ListOfShape shapeTools;
std::vector<TopoDS_Shape> shapes;
@@ -272,13 +293,13 @@ App::DocumentObjectExecReturn *Transformed::execute()
++transformIter;
for (; transformIter != transformations.end(); ++transformIter) {
// Make an explicit copy of the shape because the "true" parameter to BRepBuilderAPI_Transform
// seems to be pretty broken
// Make an explicit copy of the shape because the "true" parameter to
// BRepBuilderAPI_Transform seems to be pretty broken
BRepBuilderAPI_Copy copy(origShape);
TopoDS_Shape shape = copy.Shape();
BRepBuilderAPI_Transform mkTrf(shape, *transformIter, false); // No need to copy, now
BRepBuilderAPI_Transform mkTrf(shape, *transformIter, false); // No need to copy, now
if (!mkTrf.IsDone()) {
throw Base::CADKernelError(QT_TRANSLATE_NOOP("Exception", "Transformation failed"));
}
@@ -287,85 +308,98 @@ App::DocumentObjectExecReturn *Transformed::execute()
shapes.emplace_back(shape);
}
for (const auto& shape : shapes)
for (const auto& shape : shapes) {
shapeTools.Append(shape);
}
return shapeTools;
};
switch (mode) {
case Mode::TransformToolShapes :
// NOTE: It would be possible to build a compound from all original addShapes/subShapes and then
// transform the compounds as a whole. But we choose to apply the transformations to each
// Original separately. This way it is easier to discover what feature causes a fuse/cut
// to fail. The downside is that performance suffers when there are many originals. But it seems
// safe to assume that in most cases there are few originals and many transformations
for (auto original : originals)
{
// Extract the original shape and determine whether to cut or to fuse
Part::TopoShape fuseShape;
Part::TopoShape cutShape;
case Mode::TransformToolShapes:
// NOTE: It would be possible to build a compound from all original addShapes/subShapes
// and then transform the compounds as a whole. But we choose to apply the
// transformations to each Original separately. This way it is easier to discover what
// feature causes a fuse/cut to fail. The downside is that performance suffers when
// there are many originals. But it seems safe to assume that in most cases there are
// few originals and many transformations
for (auto original : originals) {
// Extract the original shape and determine whether to cut or to fuse
Part::TopoShape fuseShape;
Part::TopoShape cutShape;
if (original->isDerivedFrom<PartDesign::FeatureAddSub>()) {
PartDesign::FeatureAddSub* feature = static_cast<PartDesign::FeatureAddSub*>(original);
feature->getAddSubShape(fuseShape, cutShape);
if (fuseShape.isNull() && cutShape.isNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Shape of additive/subtractive feature is empty"));
gp_Trsf trsf = feature->getLocation().Transformation().Multiplied(trsfInv);
if (original->isDerivedFrom<PartDesign::FeatureAddSub>()) {
PartDesign::FeatureAddSub* feature =
static_cast<PartDesign::FeatureAddSub*>(original);
feature->getAddSubShape(fuseShape, cutShape);
if (fuseShape.isNull() && cutShape.isNull()) {
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception",
"Shape of additive/subtractive feature is empty"));
}
gp_Trsf trsf = feature->getLocation().Transformation().Multiplied(trsfInv);
#ifdef FC_USE_TNP_FIX
if (!fuseShape.isNull())
fuseShape = fuseShape.makeElementTransform(trsf);
if (!cutShape.isNull())
cutShape = cutShape.makeElementTransform(trsf);
if (!fuseShape.isNull()) {
fuseShape = fuseShape.makeElementTransform(trsf);
}
if (!cutShape.isNull()) {
cutShape = cutShape.makeElementTransform(trsf);
}
#else
if (!fuseShape.isNull())
fuseShape = fuseShape.makeTransform(trsf);
if (!cutShape.isNull())
cutShape = cutShape.makeTransform(trsf);
if (!fuseShape.isNull()) {
fuseShape = fuseShape.makeTransform(trsf);
}
if (!cutShape.isNull()) {
cutShape = cutShape.makeTransform(trsf);
}
#endif
}
else {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Only additive and subtractive features can be transformed"));
}
TopoDS_Shape current = support;
if (!fuseShape.isNull()) {
TopTools_ListOfShape shapeArguments;
shapeArguments.Append(current);
TopTools_ListOfShape shapeTools = getTransformedCompShape(fuseShape.getShape());
if (!shapeTools.IsEmpty()) {
std::unique_ptr<BRepAlgoAPI_BooleanOperation> mkBool(new BRepAlgoAPI_Fuse());
mkBool->SetArguments(shapeArguments);
mkBool->SetTools(shapeTools);
mkBool->Build();
if (!mkBool->IsDone()) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Boolean operation failed"));
}
current = mkBool->Shape();
}
}
if (!cutShape.isNull()) {
TopTools_ListOfShape shapeArguments;
shapeArguments.Append(current);
TopTools_ListOfShape shapeTools = getTransformedCompShape(cutShape.getShape());
if (!shapeTools.IsEmpty()) {
std::unique_ptr<BRepAlgoAPI_BooleanOperation> mkBool(new BRepAlgoAPI_Cut());
mkBool->SetArguments(shapeArguments);
mkBool->SetTools(shapeTools);
mkBool->Build();
if (!mkBool->IsDone()) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Boolean operation failed"));
}
current = mkBool->Shape();
else {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP(
"Exception",
"Only additive and subtractive features can be transformed"));
}
}
support = current; // Use result of this operation for fuse/cut of next original
}
break;
case Mode::TransformBody :
{
TopoDS_Shape current = support;
if (!fuseShape.isNull()) {
TopTools_ListOfShape shapeArguments;
shapeArguments.Append(current);
TopTools_ListOfShape shapeTools = getTransformedCompShape(fuseShape.getShape());
if (!shapeTools.IsEmpty()) {
std::unique_ptr<BRepAlgoAPI_BooleanOperation> mkBool(
new BRepAlgoAPI_Fuse());
mkBool->SetArguments(shapeArguments);
mkBool->SetTools(shapeTools);
mkBool->Build();
if (!mkBool->IsDone()) {
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "Boolean operation failed"));
}
current = mkBool->Shape();
}
}
if (!cutShape.isNull()) {
TopTools_ListOfShape shapeArguments;
shapeArguments.Append(current);
TopTools_ListOfShape shapeTools = getTransformedCompShape(cutShape.getShape());
if (!shapeTools.IsEmpty()) {
std::unique_ptr<BRepAlgoAPI_BooleanOperation> mkBool(new BRepAlgoAPI_Cut());
mkBool->SetArguments(shapeArguments);
mkBool->SetTools(shapeTools);
mkBool->Build();
if (!mkBool->IsDone()) {
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "Boolean operation failed"));
}
current = mkBool->Shape();
}
}
support = current; // Use result of this operation for fuse/cut of next original
}
break;
case Mode::TransformBody: {
TopTools_ListOfShape shapeArguments;
shapeArguments.Append(support);
TopTools_ListOfShape shapeTools = getTransformedCompShape(support);
@@ -375,7 +409,8 @@ App::DocumentObjectExecReturn *Transformed::execute()
mkBool->SetTools(shapeTools);
mkBool->Build();
if (!mkBool->IsDone()) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Boolean operation failed"));
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "Boolean operation failed"));
}
support = mkBool->Shape();
}
@@ -414,8 +449,9 @@ TopoDS_Shape Transformed::refineShapeIfActive(const TopoDS_Shape& oldShape) cons
return oldShape;
}
void Transformed::divideTools(const std::vector<TopoDS_Shape> &toolsIn, std::vector<TopoDS_Shape> &individualsOut,
TopoDS_Compound &compoundOut) const
void Transformed::divideTools(const std::vector<TopoDS_Shape>& toolsIn,
std::vector<TopoDS_Shape>& individualsOut,
TopoDS_Compound& compoundOut) const
{
using ShapeBoundPair = std::pair<TopoDS_Shape, Bnd_Box>;
using PairList = std::list<ShapeBoundPair>;
@@ -435,16 +471,16 @@ void Transformed::divideTools(const std::vector<TopoDS_Shape> &toolsIn, std::vec
BRep_Builder builder;
builder.MakeCompound(compoundOut);
while(!pairList.empty()) {
while (!pairList.empty()) {
PairVector currentGroup;
currentGroup.push_back(pairList.front());
pairList.pop_front();
PairList::iterator it = pairList.begin();
while(it != pairList.end()) {
while (it != pairList.end()) {
PairVector::const_iterator groupIt;
bool found(false);
for (groupIt = currentGroup.begin(); groupIt != currentGroup.end(); ++groupIt) {
if (!(*it).second.IsOut((*groupIt).second)) {//touching means is out.
if (!(*it).second.IsOut((*groupIt).second)) { // touching means is out.
found = true;
break;
}
@@ -452,7 +488,7 @@ void Transformed::divideTools(const std::vector<TopoDS_Shape> &toolsIn, std::vec
if (found) {
currentGroup.push_back(*it);
pairList.erase(it);
it=pairList.begin();
it = pairList.begin();
continue;
}
++it;
@@ -463,8 +499,9 @@ void Transformed::divideTools(const std::vector<TopoDS_Shape> &toolsIn, std::vec
}
else {
PairVector::const_iterator groupIt;
for (groupIt = currentGroup.begin(); groupIt != currentGroup.end(); ++groupIt)
for (groupIt = currentGroup.begin(); groupIt != currentGroup.end(); ++groupIt) {
individualsOut.push_back((*groupIt).first);
}
}
}
}
@@ -475,10 +512,11 @@ TopoDS_Shape Transformed::getRemainingSolids(const TopoDS_Shape& shape)
TopoDS_Compound compShape;
builder.MakeCompound(compShape);
if (shape.IsNull())
if (shape.IsNull()) {
Standard_Failure::Raise("Shape is null");
}
TopExp_Explorer xp;
xp.Init(shape,TopAbs_SOLID);
xp.Init(shape, TopAbs_SOLID);
xp.Next(); // skip the first
for (; xp.More(); xp.Next()) {
@@ -488,4 +526,4 @@ TopoDS_Shape Transformed::getRemainingSolids(const TopoDS_Shape& shape)
return TopoDS_Shape(std::move(compShape));
}
}
} // namespace PartDesign

View File

@@ -37,12 +37,13 @@ namespace PartDesign
* Abstract superclass of all features that are created by transformation of another feature
* Transformations are translation, rotation and mirroring
*/
class PartDesignExport Transformed : public PartDesign::Feature
class PartDesignExport Transformed: public PartDesign::Feature
{
PROPERTY_HEADER_WITH_OVERRIDE(PartDesign::Transformed);
public:
enum class Mode {
enum class Mode
{
TransformToolShapes,
TransformBody
};
@@ -64,51 +65,56 @@ public:
* silently return a nullptr, otherwise throw Base::Exception.
* Default is false.
*/
Part::Feature* getBaseObject(bool silent=false) const override;
Part::Feature* getBaseObject(bool silent = false) const override;
/// Return the sketch of the first original
App::DocumentObject* getSketchObject() const;
/// Get the list of transformations describing the members of the pattern
// Note: Only the Scaled feature requires the originals
virtual const std::list<gp_Trsf> getTransformations(const std::vector<App::DocumentObject*> /*originals*/) {
return std::list<gp_Trsf>(); // Default method
virtual const std::list<gp_Trsf>
getTransformations(const std::vector<App::DocumentObject*> /*originals*/)
{
return std::list<gp_Trsf>(); // Default method
}
/** @name methods override feature */
/** @name methods override feature */
//@{
/** Recalculate the feature
* Gets the transformations from the virtual getTransformations() method of the sub class
* and applies them to every member of Originals. The total number of copies including
* the untransformed Originals will be sizeof(Originals) times sizeof(getTransformations())
* If Originals is empty, execute() returns immediately without doing anything as
* the actual processing will happen in the MultiTransform feature
*/
App::DocumentObjectExecReturn *execute() override;
* Gets the transformations from the virtual getTransformations() method of the sub class
* and applies them to every member of Originals. The total number of copies including
* the untransformed Originals will be sizeof(Originals) times sizeof(getTransformations())
* If Originals is empty, execute() returns immediately without doing anything as
* the actual processing will happen in the MultiTransform feature
*/
App::DocumentObjectExecReturn* execute() override;
short mustExecute() const override;
//@}
/** returns the compound of the shapes that were rejected during the last execute
* because they did not overlap with the support
*/
* because they did not overlap with the support
*/
TopoDS_Shape rejected;
protected:
void Restore(Base::XMLReader &reader) override;
void handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, App::Property * prop) override;
void Restore(Base::XMLReader& reader) override;
void handleChangedPropertyType(Base::XMLReader& reader,
const char* TypeName,
App::Property* prop) override;
/// Return true if this feature is a child of a MultiTransform
bool isMultiTransformChild() const;
virtual void positionBySupport();
TopoDS_Shape refineShapeIfActive(const TopoDS_Shape&) const;
void divideTools(const std::vector<TopoDS_Shape> &toolsIn, std::vector<TopoDS_Shape> &individualsOut,
TopoDS_Compound &compoundOut) const;
void divideTools(const std::vector<TopoDS_Shape>& toolsIn,
std::vector<TopoDS_Shape>& individualsOut,
TopoDS_Compound& compoundOut) const;
static TopoDS_Shape getRemainingSolids(const TopoDS_Shape&);
private:
};
} //namespace PartDesign
} // namespace PartDesign
#endif // PARTDESIGN_FeatureTransformed_H
#endif // PARTDESIGN_FeatureTransformed_H