Sketcher: App - Clang-format

This commit is contained in:
Abdullah Tahiri
2023-05-18 19:01:34 +02:00
committed by abdullahtahiriyo
parent c33cdcd68a
commit 987b4bda2a
40 changed files with 9714 additions and 7322 deletions

View File

@@ -29,15 +29,17 @@
#include "Constraint.h"
namespace Sketcher {
namespace Sketcher
{
struct ConstraintIds {
Base::Vector3d v;
int First;
int Second;
Sketcher::PointPos FirstPos;
Sketcher::PointPos SecondPos;
Sketcher::ConstraintType Type;
struct ConstraintIds
{
Base::Vector3d v;
int First;
int Second;
Sketcher::PointPos FirstPos;
Sketcher::PointPos SecondPos;
Sketcher::ConstraintType Type;
};
struct Constraint_Equal
@@ -45,21 +47,21 @@ struct Constraint_Equal
using argument_type = ConstraintIds;
using result_type = bool;
struct Sketcher::ConstraintIds c;
explicit Constraint_Equal(const ConstraintIds& c) : c(c)
{
}
explicit Constraint_Equal(const ConstraintIds& c)
: c(c)
{}
bool operator()(const ConstraintIds& x) const
{
if (c.First == x.First && c.FirstPos == x.FirstPos &&
c.Second == x.Second && c.SecondPos == x.SecondPos)
if (c.First == x.First && c.FirstPos == x.FirstPos && c.Second == x.Second
&& c.SecondPos == x.SecondPos)
return true;
if (c.Second == x.First && c.SecondPos == x.FirstPos &&
c.First == x.Second && c.FirstPos == x.SecondPos)
if (c.Second == x.First && c.SecondPos == x.FirstPos && c.First == x.Second
&& c.FirstPos == x.SecondPos)
return true;
return false;
}
};
} //namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_ANALYSE_H
#endif// SKETCHER_ANALYSE_H

View File

@@ -43,7 +43,8 @@
#include "SolverGeometryExtension.h"
namespace Sketcher {
namespace Sketcher
{
extern PyObject* initModule();
}
@@ -54,7 +55,7 @@ PyMOD_INIT_FUNC(Sketcher)
try {
Base::Interpreter().runString("import Part");
}
catch(const Base::Exception& e) {
catch (const Base::Exception& e) {
PyErr_SetString(PyExc_ImportError, e.what());
PyMOD_Return(nullptr);
}
@@ -62,29 +63,33 @@ PyMOD_INIT_FUNC(Sketcher)
PyObject* sketcherModule = Sketcher::initModule();
// Add Types to module
Base::Interpreter().addType(&Sketcher::ConstraintPy ::Type,sketcherModule,"Constraint");
Base::Interpreter().addType(&Sketcher::SketchPy ::Type,sketcherModule,"Sketch");
Base::Interpreter().addType(&Sketcher::ExternalGeometryExtensionPy ::Type,sketcherModule,"ExternalGeometryExtension");
Base::Interpreter().addType(&Sketcher::SketchGeometryExtensionPy ::Type,sketcherModule,"SketchGeometryExtension");
Base::Interpreter().addType(&Sketcher::GeometryFacadePy ::Type,sketcherModule,"GeometryFacade");
Base::Interpreter().addType(&Sketcher::ExternalGeometryFacadePy ::Type,sketcherModule,"ExternalGeometryFacade");
Base::Interpreter().addType(&Sketcher::ConstraintPy ::Type, sketcherModule, "Constraint");
Base::Interpreter().addType(&Sketcher::SketchPy ::Type, sketcherModule, "Sketch");
Base::Interpreter().addType(
&Sketcher::ExternalGeometryExtensionPy ::Type, sketcherModule, "ExternalGeometryExtension");
Base::Interpreter().addType(
&Sketcher::SketchGeometryExtensionPy ::Type, sketcherModule, "SketchGeometryExtension");
Base::Interpreter().addType(
&Sketcher::GeometryFacadePy ::Type, sketcherModule, "GeometryFacade");
Base::Interpreter().addType(
&Sketcher::ExternalGeometryFacadePy ::Type, sketcherModule, "ExternalGeometryFacade");
// NOTE: To finish the initialization of our own type objects we must
// call PyType_Ready, otherwise we run into a segmentation fault, later on.
// This function is responsible for adding inherited slots from a type's base class.
Sketcher::SketchGeometryExtension ::init();
Sketcher::ExternalGeometryExtension ::init();
Sketcher::SolverGeometryExtension ::init();
Sketcher::GeometryFacade ::init();
Sketcher::ExternalGeometryFacade ::init();
Sketcher::SketchObjectSF ::init();
Sketcher::SketchObject ::init();
Sketcher::SketchObjectPython ::init();
Sketcher::Sketch ::init();
Sketcher::Constraint ::init();
Sketcher::PropertyConstraintList ::init();
Sketcher::SketchGeometryExtension ::init();
Sketcher::ExternalGeometryExtension ::init();
Sketcher::SolverGeometryExtension ::init();
Sketcher::GeometryFacade ::init();
Sketcher::ExternalGeometryFacade ::init();
Sketcher::SketchObjectSF ::init();
Sketcher::SketchObject ::init();
Sketcher::SketchObjectPython ::init();
Sketcher::Sketch ::init();
Sketcher::Constraint ::init();
Sketcher::PropertyConstraintList ::init();
Base::Console().Log("Loading Sketcher module... done\n");

View File

@@ -32,31 +32,32 @@
#include "SketchObjectSF.h"
namespace Sketcher {
class Module : public Py::ExtensionModule<Module>
namespace Sketcher
{
class Module: public Py::ExtensionModule<Module>
{
public:
Module() : Py::ExtensionModule<Module>("Sketcher")
Module()
: Py::ExtensionModule<Module>("Sketcher")
{
add_varargs_method("open",&Module::open
);
add_varargs_method("insert",&Module::insert
);
initialize("This module is the Sketcher module."); // register with Python
add_varargs_method("open", &Module::open);
add_varargs_method("insert", &Module::insert);
initialize("This module is the Sketcher module.");// register with Python
}
~Module() override {}
~Module() override
{}
private:
Py::Object open(const Py::Tuple& args)
{
char* Name;
if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name))
if (!PyArg_ParseTuple(args.ptr(), "et", "utf-8", &Name))
throw Py::Exception();
std::string EncodedName = std::string(Name);
PyMem_Free(Name);
//Base::Console().Log("Open in Part with %s",Name);
// Base::Console().Log("Open in Part with %s",Name);
Base::FileInfo file(EncodedName.c_str());
// extract extension
@@ -64,33 +65,34 @@ private:
throw Py::RuntimeError("No file extension");
throw Py::RuntimeError("Unknown file extension");
//return Py::None();
// return Py::None();
}
Py::Object insert(const Py::Tuple& args)
{
char* Name;
const char* DocName;
if (!PyArg_ParseTuple(args.ptr(), "ets","utf-8",&Name,&DocName))
if (!PyArg_ParseTuple(args.ptr(), "ets", "utf-8", &Name, &DocName))
throw Py::Exception();
std::string EncodedName = std::string(Name);
PyMem_Free(Name);
try {
//Base::Console().Log("Insert in Part with %s",Name);
// Base::Console().Log("Insert in Part with %s",Name);
Base::FileInfo file(EncodedName.c_str());
// extract extension
if (file.extension().empty())
throw Py::RuntimeError("No file extension");
App::Document *pcDoc = App::GetApplication().getDocument(DocName);
App::Document* pcDoc = App::GetApplication().getDocument(DocName);
if (!pcDoc) {
pcDoc = App::GetApplication().newDocument(DocName);
}
if (file.hasExtension("skf")) {
Sketcher::SketchObjectSF *pcFeature = static_cast<Sketcher::SketchObjectSF *>(pcDoc->addObject("Sketcher::SketchObjectSF",file.fileNamePure().c_str()));
Sketcher::SketchObjectSF* pcFeature = static_cast<Sketcher::SketchObjectSF*>(
pcDoc->addObject("Sketcher::SketchObjectSF", file.fileNamePure().c_str()));
pcFeature->SketchFlatFile.setValue(EncodedName.c_str());
pcDoc->recompute();
@@ -113,4 +115,4 @@ PyObject* initModule()
}
/// @endcond
} // namespace Sketcher
}// namespace Sketcher

View File

@@ -22,13 +22,13 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
# include <QDateTime>
#include <QDateTime>
#include <cmath>
#endif
#include <Base/Reader.h>
#include <Base/Writer.h>
#include <Base/Tools.h>
#include <Base/Writer.h>
#include "Constraint.h"
#include "ConstraintPy.h"
@@ -41,21 +41,21 @@ using namespace Base;
TYPESYSTEM_SOURCE(Sketcher::Constraint, Base::Persistence)
Constraint::Constraint()
: Value(0.0),
Type(None),
AlignmentType(Undef),
First(GeoEnum::GeoUndef),
FirstPos(PointPos::none),
Second(GeoEnum::GeoUndef),
SecondPos(PointPos::none),
Third(GeoEnum::GeoUndef),
ThirdPos(PointPos::none),
LabelDistance(10.f),
LabelPosition(0.f),
isDriving(true),
InternalAlignmentIndex(-1),
isInVirtualSpace(false),
isActive(true)
: Value(0.0),
Type(None),
AlignmentType(Undef),
First(GeoEnum::GeoUndef),
FirstPos(PointPos::none),
Second(GeoEnum::GeoUndef),
SecondPos(PointPos::none),
Third(GeoEnum::GeoUndef),
ThirdPos(PointPos::none),
LabelDistance(10.f),
LabelPosition(0.f),
isDriving(true),
InternalAlignmentIndex(-1),
isInVirtualSpace(false),
isActive(true)
{
// Initialize a random number generator, to avoid Valgrind false positives.
static boost::mt19937 ran;
@@ -70,14 +70,14 @@ Constraint::Constraint()
tag = gen();
}
Constraint *Constraint::clone() const
Constraint* Constraint::clone() const
{
return new Constraint(*this);
}
Constraint *Constraint::copy() const
Constraint* Constraint::copy() const
{
Constraint *temp = new Constraint();
Constraint* temp = new Constraint();
temp->Value = this->Value;
temp->Type = this->Type;
temp->AlignmentType = this->AlignmentType;
@@ -98,7 +98,7 @@ Constraint *Constraint::copy() const
return temp;
}
PyObject *Constraint::getPyObject()
PyObject* Constraint::getPyObject()
{
return new ConstraintPy(new Constraint(*this));
}
@@ -107,80 +107,79 @@ Quantity Constraint::getPresentationValue() const
{
Quantity quantity;
switch (Type) {
case Distance:
case Radius:
case Diameter:
case DistanceX:
case DistanceY:
quantity.setValue(Value);
quantity.setUnit(Unit::Length);
break;
case Angle:
quantity.setValue(toDegrees<double>(Value));
quantity.setUnit(Unit::Angle);
break;
case SnellsLaw:
case Weight:
quantity.setValue(Value);
break;
default:
quantity.setValue(Value);
break;
case Distance:
case Radius:
case Diameter:
case DistanceX:
case DistanceY:
quantity.setValue(Value);
quantity.setUnit(Unit::Length);
break;
case Angle:
quantity.setValue(toDegrees<double>(Value));
quantity.setUnit(Unit::Angle);
break;
case SnellsLaw:
case Weight:
quantity.setValue(Value);
break;
default:
quantity.setValue(Value);
break;
}
QuantityFormat format = quantity.getFormat();
format.option = QuantityFormat::None;
format.format = QuantityFormat::Default;
format.precision = 6; // QString's default
format.precision = 6;// QString's default
quantity.setFormat(format);
return quantity;
}
unsigned int Constraint::getMemSize () const
unsigned int Constraint::getMemSize() const
{
return 0;
}
void Constraint::Save (Writer &writer) const
void Constraint::Save(Writer& writer) const
{
std::string encodeName = encodeAttribute(Name);
writer.Stream() << writer.ind() << "<Constrain "
<< "Name=\"" << encodeName << "\" "
<< "Type=\"" << (int)Type << "\" ";
if(this->Type==InternalAlignment)
writer.Stream()
<< "InternalAlignmentType=\"" << (int)AlignmentType << "\" "
<< "InternalAlignmentIndex=\"" << InternalAlignmentIndex << "\" ";
writer.Stream()
<< "Value=\"" << Value << "\" "
<< "First=\"" << First << "\" "
<< "FirstPos=\"" << (int) FirstPos << "\" "
<< "Second=\"" << Second << "\" "
<< "SecondPos=\"" << (int) SecondPos << "\" "
<< "Third=\"" << Third << "\" "
<< "ThirdPos=\"" << (int) ThirdPos << "\" "
<< "LabelDistance=\"" << LabelDistance << "\" "
<< "LabelPosition=\"" << LabelPosition << "\" "
<< "IsDriving=\"" << (int)isDriving << "\" "
<< "IsInVirtualSpace=\"" << (int)isInVirtualSpace << "\" "
<< "IsActive=\"" << (int)isActive << "\" />"
writer.Stream() << writer.ind() << "<Constrain "
<< "Name=\"" << encodeName << "\" "
<< "Type=\"" << (int)Type << "\" ";
if (this->Type == InternalAlignment)
writer.Stream() << "InternalAlignmentType=\"" << (int)AlignmentType << "\" "
<< "InternalAlignmentIndex=\"" << InternalAlignmentIndex << "\" ";
writer.Stream() << "Value=\"" << Value << "\" "
<< "First=\"" << First << "\" "
<< "FirstPos=\"" << (int)FirstPos << "\" "
<< "Second=\"" << Second << "\" "
<< "SecondPos=\"" << (int)SecondPos << "\" "
<< "Third=\"" << Third << "\" "
<< "ThirdPos=\"" << (int)ThirdPos << "\" "
<< "LabelDistance=\"" << LabelDistance << "\" "
<< "LabelPosition=\"" << LabelPosition << "\" "
<< "IsDriving=\"" << (int)isDriving << "\" "
<< "IsInVirtualSpace=\"" << (int)isInVirtualSpace << "\" "
<< "IsActive=\"" << (int)isActive << "\" />"
<< std::endl;
<< std::endl;
}
void Constraint::Restore(XMLReader &reader)
void Constraint::Restore(XMLReader& reader)
{
reader.readElement("Constrain");
Name = reader.getAttribute("Name");
Type = static_cast<ConstraintType>(reader.getAttributeAsInteger("Type"));
Value = reader.getAttributeAsFloat("Value");
First = reader.getAttributeAsInteger("First");
FirstPos = static_cast<PointPos>(reader.getAttributeAsInteger("FirstPos"));
Second = reader.getAttributeAsInteger("Second");
Name = reader.getAttribute("Name");
Type = static_cast<ConstraintType>(reader.getAttributeAsInteger("Type"));
Value = reader.getAttributeAsFloat("Value");
First = reader.getAttributeAsInteger("First");
FirstPos = static_cast<PointPos>(reader.getAttributeAsInteger("FirstPos"));
Second = reader.getAttributeAsInteger("Second");
SecondPos = static_cast<PointPos>(reader.getAttributeAsInteger("SecondPos"));
if(this->Type==InternalAlignment) {
AlignmentType = static_cast<InternalAlignmentType>(reader.getAttributeAsInteger("InternalAlignmentType"));
if (this->Type == InternalAlignment) {
AlignmentType = static_cast<InternalAlignmentType>(
reader.getAttributeAsInteger("InternalAlignmentType"));
if (reader.hasAttribute("InternalAlignmentIndex"))
InternalAlignmentIndex = reader.getAttributeAsInteger("InternalAlignmentIndex");
@@ -191,7 +190,7 @@ void Constraint::Restore(XMLReader &reader)
// read the third geo group if present
if (reader.hasAttribute("Third")) {
Third = reader.getAttributeAsInteger("Third");
Third = reader.getAttributeAsInteger("Third");
ThirdPos = static_cast<PointPos>(reader.getAttributeAsInteger("ThirdPos"));
}

View File

@@ -36,11 +36,13 @@
namespace Sketcher
{
/*!
Important note: New constraint types must be always added at the end but before 'NumConstraintTypes'.
This is mandatory in order to keep the handling of constraint types upward compatible which means that
this program version ignores later introduced constraint types when reading them from a project file.
Important note: New constraint types must be always added at the end but before
'NumConstraintTypes'. This is mandatory in order to keep the handling of constraint types upward
compatible which means that this program version ignores later introduced constraint types when
reading them from a project file.
*/
enum ConstraintType : int {
enum ConstraintType : int
{
None = 0,
Coincident = 1,
Horizontal = 2,
@@ -61,26 +63,27 @@ enum ConstraintType : int {
Block = 17,
Diameter = 18,
Weight = 19,
NumConstraintTypes // must be the last item!
NumConstraintTypes// must be the last item!
};
enum InternalAlignmentType {
Undef = 0,
EllipseMajorDiameter = 1,
EllipseMinorDiameter = 2,
EllipseFocus1 = 3,
EllipseFocus2 = 4,
HyperbolaMajor = 5,
HyperbolaMinor = 6,
HyperbolaFocus = 7,
ParabolaFocus = 8,
BSplineControlPoint = 9,
BSplineKnotPoint = 10,
ParabolaFocalAxis = 11,
NumInternalAlignmentType // must be the last item!
enum InternalAlignmentType
{
Undef = 0,
EllipseMajorDiameter = 1,
EllipseMinorDiameter = 2,
EllipseFocus1 = 3,
EllipseFocus2 = 4,
HyperbolaMajor = 5,
HyperbolaMinor = 6,
HyperbolaFocus = 7,
ParabolaFocus = 8,
BSplineControlPoint = 9,
BSplineKnotPoint = 10,
ParabolaFocalAxis = 11,
NumInternalAlignmentType// must be the last item!
};
class SketcherExport Constraint : public Base::Persistence
class SketcherExport Constraint: public Base::Persistence
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -90,7 +93,7 @@ public:
// Constraints objects explicitly not copiable with standard methods
// Copy constructor is private for internal use only
Constraint &operator =(const Constraint &a) = delete;
Constraint& operator=(const Constraint& a) = delete;
// Constraints objects explicitly not movable
Constraint(Constraint&&) = delete;
@@ -98,55 +101,92 @@ public:
~Constraint() override = default;
Constraint *clone() const; // does copy the tag, it will be treated as a rename by the expression engine.
Constraint *copy() const; // does not copy the tag, but generates a new one
// does copy the tag, it will be treated as a rename by the expression engine.
Constraint* clone() const;
// does not copy the tag, but generates a new one
Constraint* copy() const;
// from base class
unsigned int getMemSize() const override;
void Save(Base::Writer &/*writer*/) const override;
void Restore(Base::XMLReader &/*reader*/) override;
void Save(Base::Writer& /*writer*/) const override;
void Restore(Base::XMLReader& /*reader*/) override;
PyObject *getPyObject() override;
PyObject* getPyObject() override;
Base::Quantity getPresentationValue() const;
inline void setValue(double newValue) {
inline void setValue(double newValue)
{
Value = newValue;
}
inline double getValue() const {
inline double getValue() const
{
return Value;
}
inline bool isDimensional() const {
return Type == Distance || Type == DistanceX || Type == DistanceY ||
Type == Radius || Type == Diameter || Type == Angle || Type == SnellsLaw || Type == Weight;
inline bool isDimensional() const
{
return Type == Distance || Type == DistanceX || Type == DistanceY || Type == Radius
|| Type == Diameter || Type == Angle || Type == SnellsLaw || Type == Weight;
}
/// utility function to swap the index in First/Second/Third of the provided constraint from the fromGeoId GeoId to toGeoId
/// utility function to swap the index in First/Second/Third of the provided constraint from the
/// fromGeoId GeoId to toGeoId
void substituteIndex(int fromGeoId, int toGeoId);
std::string typeToString() const {return typeToString(Type);}
std::string typeToString() const
{
return typeToString(Type);
}
static std::string typeToString(ConstraintType type);
std::string internalAlignmentTypeToString() const {return internalAlignmentTypeToString(AlignmentType);}
std::string internalAlignmentTypeToString() const
{
return internalAlignmentTypeToString(AlignmentType);
}
static std::string internalAlignmentTypeToString(InternalAlignmentType alignment);
friend class PropertyConstraintList;
private:
Constraint(const Constraint&) = default; // only for internal use
Constraint(const Constraint&) = default;// only for internal use
private:
double Value;
constexpr static std::array<const char *,ConstraintType::NumConstraintTypes> type2str {
{ "None", "Horizontal", "Vertical","Parallel", "Tangent", "Distance", "DistanceX", "DistanceY", "Angle", "Perpendicular", "Radius",
"Equal", "PointOnObject", "Symmetric", "InternalAlignment", "SnellsLaw", "Block", "Diameter", "Weight"}
};
constexpr static std::array<const char*, ConstraintType::NumConstraintTypes> type2str {
{"None",
"Horizontal",
"Vertical",
"Parallel",
"Tangent",
"Distance",
"DistanceX",
"DistanceY",
"Angle",
"Perpendicular",
"Radius",
"Equal",
"PointOnObject",
"Symmetric",
"InternalAlignment",
"SnellsLaw",
"Block",
"Diameter",
"Weight"}};
constexpr static std::array<const char *,InternalAlignmentType::NumInternalAlignmentType> internalAlignmentType2str {
{ "Undef", "EllipseMajorDiameter", "EllipseMinorDiameter", "EllipseFocus1", "EllipseFocus2", "HyperbolaMajor", "HyperbolaMinor",
"HyperbolaFocus", "ParabolaFocus", "BSplineControlPoint", "BSplineKnotPoint", "ParabolaFocalAxis"}
};
constexpr static std::array<const char*, InternalAlignmentType::NumInternalAlignmentType>
internalAlignmentType2str {{"Undef",
"EllipseMajorDiameter",
"EllipseMinorDiameter",
"EllipseFocus1",
"EllipseFocus2",
"HyperbolaMajor",
"HyperbolaMinor",
"HyperbolaFocus",
"ParabolaFocus",
"BSplineControlPoint",
"BSplineKnotPoint",
"ParabolaFocalAxis"}};
public:
ConstraintType Type;
@@ -161,7 +201,9 @@ public:
float LabelDistance;
float LabelPosition;
bool isDriving;
int InternalAlignmentIndex; // Note: for InternalAlignment Type this index indexes equal internal geometry elements (e.g. index of pole in a bspline). It is not a GeoId!!
// Note: for InternalAlignment Type this index indexes equal internal geometry elements (e.g.
// index of pole in a bspline). It is not a GeoId!!
int InternalAlignmentIndex;
bool isInVirtualSpace;
bool isActive;
@@ -170,7 +212,7 @@ protected:
boost::uuids::uuid tag;
};
} //namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_CONSTRAINT_H
#endif// SKETCHER_CONSTRAINT_H

View File

@@ -22,18 +22,19 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
#include <sstream>
#endif
#include <Base/QuantityPy.h>
#include "ConstraintPy.h"
#include "ConstraintPy.cpp"
using namespace Sketcher;
PyObject *ConstraintPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
PyObject* ConstraintPy::PyMake(struct _typeobject*, PyObject*, PyObject*)// Python wrapper
{
// create a new instance of ConstraintPy and the Twin object
return new ConstraintPy(new Constraint);
@@ -48,17 +49,17 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
PyErr_Clear();
char *ConstraintType;
int FirstIndex = GeoEnum::GeoUndef;
int FirstPos = static_cast<int>(PointPos::none);
int SecondIndex= GeoEnum::GeoUndef;
int SecondPos = static_cast<int>(PointPos::none);
int ThirdIndex = GeoEnum::GeoUndef;
int ThirdPos = static_cast<int>(PointPos::none);
double Value = 0;
char* ConstraintType;
int FirstIndex = GeoEnum::GeoUndef;
int FirstPos = static_cast<int>(PointPos::none);
int SecondIndex = GeoEnum::GeoUndef;
int SecondPos = static_cast<int>(PointPos::none);
int ThirdIndex = GeoEnum::GeoUndef;
int ThirdPos = static_cast<int>(PointPos::none);
double Value = 0;
int intArg1, intArg2, intArg3, intArg4, intArg5;
// Note: In Python 2.x PyArg_ParseTuple prints a warning if a float is given but an integer is expected.
// This means we must use a PyObject and check afterwards if it's a float or integer.
// Note: In Python 2.x PyArg_ParseTuple prints a warning if a float is given but an integer is
// expected. This means we must use a PyObject and check afterwards if it's a float or integer.
PyObject* index_or_value;
PyObject* oNumArg4;
PyObject* oNumArg5;
@@ -66,17 +67,17 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
// ConstraintType, GeoIndex
if (PyArg_ParseTuple(args, "si", &ConstraintType, &FirstIndex)) {
if (strcmp("Horizontal",ConstraintType) == 0) {
if (strcmp("Horizontal", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Horizontal;
this->getConstraintPtr()->First = FirstIndex;
return 0;
}
else if (strcmp("Vertical",ConstraintType) == 0) {
else if (strcmp("Vertical", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Vertical;
this->getConstraintPtr()->First = FirstIndex;
return 0;
}
else if (strcmp("Block",ConstraintType) == 0) {
else if (strcmp("Block", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Block;
this->getConstraintPtr()->First = FirstIndex;
return 0;
@@ -89,32 +90,32 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
if (PyLong_Check(index_or_value)) {
SecondIndex = PyLong_AsLong(index_or_value);
bool valid = false;
if (strcmp("Tangent",ConstraintType) == 0) {
if (strcmp("Tangent", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Tangent;
valid = true;
}
else if (strcmp("Parallel",ConstraintType) == 0) {
else if (strcmp("Parallel", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Parallel;
valid = true;
}
else if (strcmp("Perpendicular",ConstraintType) == 0) {
else if (strcmp("Perpendicular", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Perpendicular;
valid = true;
}
else if (strcmp("Equal",ConstraintType) == 0) {
else if (strcmp("Equal", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Equal;
valid = true;
}
else if (strstr(ConstraintType,"InternalAlignment")) {
else if (strstr(ConstraintType, "InternalAlignment")) {
this->getConstraintPtr()->Type = InternalAlignment;
valid = true;
if(strstr(ConstraintType,"EllipseMajorDiameter"))
this->getConstraintPtr()->AlignmentType=EllipseMajorDiameter;
else if(strstr(ConstraintType,"EllipseMinorDiameter"))
this->getConstraintPtr()->AlignmentType=EllipseMinorDiameter;
if (strstr(ConstraintType, "EllipseMajorDiameter"))
this->getConstraintPtr()->AlignmentType = EllipseMajorDiameter;
else if (strstr(ConstraintType, "EllipseMinorDiameter"))
this->getConstraintPtr()->AlignmentType = EllipseMinorDiameter;
else {
this->getConstraintPtr()->AlignmentType=Undef;
this->getConstraintPtr()->AlignmentType = Undef;
valid = false;
}
}
@@ -126,45 +127,46 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
}
}
// ConstraintType, GeoIndex, Value
if (PyNumber_Check(index_or_value)) { // can be float or int
if (PyNumber_Check(index_or_value)) {// can be float or int
Value = PyFloat_AsDouble(index_or_value);
bool valid = false;
if (strcmp("Distance",ConstraintType) == 0 ) {
if (strcmp("Distance", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Distance;
valid = true;
}
else if (strcmp("Angle",ConstraintType) == 0 ) {
else if (strcmp("Angle", ConstraintType) == 0) {
if (PyObject_TypeCheck(index_or_value, &(Base::QuantityPy::Type))) {
Base::Quantity q = *(static_cast<Base::QuantityPy*>(index_or_value)->getQuantityPtr());
Base::Quantity q =
*(static_cast<Base::QuantityPy*>(index_or_value)->getQuantityPtr());
if (q.getUnit() == Base::Unit::Angle)
Value = q.getValueAs(Base::Quantity::Radian);
}
this->getConstraintPtr()->Type = Angle;
valid = true;
}
else if (strcmp("DistanceX",ConstraintType) == 0) {
else if (strcmp("DistanceX", ConstraintType) == 0) {
this->getConstraintPtr()->Type = DistanceX;
valid = true;
}
else if (strcmp("DistanceY",ConstraintType) == 0) {
else if (strcmp("DistanceY", ConstraintType) == 0) {
this->getConstraintPtr()->Type = DistanceY;
valid = true;
}
else if (strcmp("Radius",ConstraintType) == 0) {
else if (strcmp("Radius", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Radius;
// set a value that is out of range of result of atan2
// this value is handled in ViewProviderSketch
this->getConstraintPtr()->LabelPosition = 10;
valid = true;
}
else if (strcmp("Diameter",ConstraintType) == 0) {
else if (strcmp("Diameter", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Diameter;
// set a value that is out of range of result of atan2
// this value is handled in ViewProviderSketch
this->getConstraintPtr()->LabelPosition = 10;
valid = true;
}
else if (strcmp("Weight",ConstraintType) == 0) {
else if (strcmp("Weight", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Weight;
// set a value that is out of range of result of atan2
// this value is handled in ViewProviderSketch
@@ -172,7 +174,7 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
valid = true;
}
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->setValue(Value);
return 0;
}
@@ -198,65 +200,66 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
this->getConstraintPtr()->Type = PointOnObject;
valid = true;
}
else if (strstr(ConstraintType,"InternalAlignment")) {
else if (strstr(ConstraintType, "InternalAlignment")) {
this->getConstraintPtr()->Type = InternalAlignment;
valid = true;
if(strstr(ConstraintType,"EllipseFocus1"))
this->getConstraintPtr()->AlignmentType=EllipseFocus1;
else if(strstr(ConstraintType,"EllipseFocus2"))
this->getConstraintPtr()->AlignmentType=EllipseFocus2;
if (strstr(ConstraintType, "EllipseFocus1"))
this->getConstraintPtr()->AlignmentType = EllipseFocus1;
else if (strstr(ConstraintType, "EllipseFocus2"))
this->getConstraintPtr()->AlignmentType = EllipseFocus2;
else {
this->getConstraintPtr()->AlignmentType=Undef;
this->getConstraintPtr()->AlignmentType = Undef;
valid = false;
}
}
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(FirstPos);
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->Second = SecondIndex;
return 0;
}
}
// ConstraintType, GeoIndex1, GeoIndex2, Value
// ConstraintType, GeoIndex, PosIndex, Value
if (PyNumber_Check(index_or_value)) { // can be float or int
if (PyNumber_Check(index_or_value)) {// can be float or int
SecondIndex = any_index;
Value = PyFloat_AsDouble(index_or_value);
if (strcmp("Angle",ConstraintType) == 0) {
if (strcmp("Angle", ConstraintType) == 0) {
if (PyObject_TypeCheck(index_or_value, &(Base::QuantityPy::Type))) {
Base::Quantity q = *(static_cast<Base::QuantityPy*>(index_or_value)->getQuantityPtr());
Base::Quantity q =
*(static_cast<Base::QuantityPy*>(index_or_value)->getQuantityPtr());
if (q.getUnit() == Base::Unit::Angle)
Value = q.getValueAs(Base::Quantity::Radian);
}
this->getConstraintPtr()->Type = Angle;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->Type = Angle;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->setValue(Value);
return 0;
}
else if (strcmp("Distance",ConstraintType) == 0) {
else if (strcmp("Distance", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Distance;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->setValue(Value);
return 0;
}
else if (strcmp("DistanceX",ConstraintType) == 0) {
else if (strcmp("DistanceX", ConstraintType) == 0) {
FirstPos = SecondIndex;
SecondIndex = -1;
this->getConstraintPtr()->Type = DistanceX;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(FirstPos);
this->getConstraintPtr()->setValue(Value);
return 0;
}
else if (strcmp("DistanceY",ConstraintType) == 0) {
else if (strcmp("DistanceY", ConstraintType) == 0) {
FirstPos = SecondIndex;
SecondIndex = -1;
this->getConstraintPtr()->Type = DistanceY;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(FirstPos);
this->getConstraintPtr()->setValue(Value);
return 0;
@@ -292,68 +295,67 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
}
else if (strcmp("TangentViaPoint", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Tangent;
//valid = true;//non-standard assignment
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Second = intArg2;
// valid = true;//non-standard assignment
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Second = intArg2;
this->getConstraintPtr()->SecondPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Third = intArg3;
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(intArg4);
this->getConstraintPtr()->Third = intArg3;
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(intArg4);
return 0;
}
else if (strcmp("PerpendicularViaPoint", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Perpendicular;
//valid = true;//non-standard assignment
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Second = intArg2;
// valid = true;//non-standard assignment
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Second = intArg2;
this->getConstraintPtr()->SecondPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Third = intArg3;
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(intArg4);
this->getConstraintPtr()->Third = intArg3;
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(intArg4);
return 0;
}
else if (strstr(ConstraintType,"InternalAlignment")) { // InteralAlignment with InternalElementIndex argument
else if (strstr(ConstraintType, "InternalAlignment")) {// InteralAlignment with
// InternalElementIndex argument
this->getConstraintPtr()->Type = InternalAlignment;
valid = true;
if (strstr(ConstraintType,"BSplineControlPoint")) {
this->getConstraintPtr()->AlignmentType=BSplineControlPoint;
if (strstr(ConstraintType, "BSplineControlPoint")) {
this->getConstraintPtr()->AlignmentType = BSplineControlPoint;
}
else if (strstr(ConstraintType,"BSplineKnotPoint")) {
this->getConstraintPtr()->AlignmentType=BSplineKnotPoint;
else if (strstr(ConstraintType, "BSplineKnotPoint")) {
this->getConstraintPtr()->AlignmentType = BSplineKnotPoint;
}
else
{
this->getConstraintPtr()->AlignmentType=Undef;
else {
this->getConstraintPtr()->AlignmentType = Undef;
valid = false;
}
if (valid) {
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->InternalAlignmentIndex = intArg4;
return 0;
}
}
if (valid) {
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->SecondPos = static_cast<Sketcher::PointPos>(intArg4);
return 0;
}
}
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, Value
if (PyNumber_Check(oNumArg4)) { // can be float or int
if (PyNumber_Check(oNumArg4)) {// can be float or int
Value = PyFloat_AsDouble(oNumArg4);
if (strcmp("Distance",ConstraintType) == 0 ) {
if (strcmp("Distance", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Distance;
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->setValue(Value);
return 0;
}
@@ -361,66 +363,69 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "siiiiO", &ConstraintType, &intArg1, &intArg2, &intArg3, &intArg4, &oNumArg5)) {
if (PyArg_ParseTuple(
args, "siiiiO", &ConstraintType, &intArg1, &intArg2, &intArg3, &intArg4, &oNumArg5)) {
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, PosIndex2, GeoIndex3
if (PyLong_Check(oNumArg5)) {
intArg5 = PyLong_AsLong(oNumArg5);
if (strcmp("Symmetric",ConstraintType) == 0 ) {
if (strcmp("Symmetric", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Symmetric;
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->SecondPos = static_cast<Sketcher::PointPos>(intArg4);
this->getConstraintPtr()->Third = intArg5;
this->getConstraintPtr()->Third = intArg5;
return 0;
}
}
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, PosIndex2, Value
if (PyNumber_Check(oNumArg5)) { // can be float or int
if (PyNumber_Check(oNumArg5)) {// can be float or int
Value = PyFloat_AsDouble(oNumArg5);
bool valid=false;
if (strcmp("Distance",ConstraintType) == 0 ) {
bool valid = false;
if (strcmp("Distance", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Distance;
valid = true;
}
else if (strcmp("DistanceX",ConstraintType) == 0) {
else if (strcmp("DistanceX", ConstraintType) == 0) {
this->getConstraintPtr()->Type = DistanceX;
valid = true;
}
else if (strcmp("DistanceY",ConstraintType) == 0) {
else if (strcmp("DistanceY", ConstraintType) == 0) {
this->getConstraintPtr()->Type = DistanceY;
valid = true;
}
else if (strcmp("Angle",ConstraintType) == 0 ) {
else if (strcmp("Angle", ConstraintType) == 0) {
if (PyObject_TypeCheck(oNumArg5, &(Base::QuantityPy::Type))) {
Base::Quantity q = *(static_cast<Base::QuantityPy*>(oNumArg5)->getQuantityPtr());
Base::Quantity q =
*(static_cast<Base::QuantityPy*>(oNumArg5)->getQuantityPtr());
if (q.getUnit() == Base::Unit::Angle)
Value = q.getValueAs(Base::Quantity::Radian);
}
this->getConstraintPtr()->Type = Angle;
valid = true;
}
else if (strcmp("AngleViaPoint",ConstraintType) == 0 ) {
else if (strcmp("AngleViaPoint", ConstraintType) == 0) {
if (PyObject_TypeCheck(oNumArg5, &(Base::QuantityPy::Type))) {
Base::Quantity q = *(static_cast<Base::QuantityPy*>(oNumArg5)->getQuantityPtr());
Base::Quantity q =
*(static_cast<Base::QuantityPy*>(oNumArg5)->getQuantityPtr());
if (q.getUnit() == Base::Unit::Angle)
Value = q.getValueAs(Base::Quantity::Radian);
}
this->getConstraintPtr()->Type = Angle;
//valid = true;//non-standard assignment
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Second = intArg2; //let's goof up all the terminology =)
// valid = true;//non-standard assignment
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Second = intArg2;// let's goof up all the terminology =)
this->getConstraintPtr()->SecondPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Third = intArg3;
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(intArg4);
this->getConstraintPtr()->Third = intArg3;
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(intArg4);
this->getConstraintPtr()->setValue(Value);
return 0;
}
if (valid) {
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->First = intArg1;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(intArg2);
this->getConstraintPtr()->Second = intArg3;
this->getConstraintPtr()->SecondPos = static_cast<Sketcher::PointPos>(intArg4);
this->getConstraintPtr()->setValue(Value);
return 0;
@@ -429,31 +434,39 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "siiiiiO", &ConstraintType, &FirstIndex, &FirstPos, &SecondIndex, &SecondPos, &ThirdIndex, &index_or_value)) {
if (PyArg_ParseTuple(args,
"siiiiiO",
&ConstraintType,
&FirstIndex,
&FirstPos,
&SecondIndex,
&SecondPos,
&ThirdIndex,
&index_or_value)) {
if (PyLong_Check(index_or_value)) {
ThirdPos = PyLong_AsLong(index_or_value);
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, PosIndex2, GeoIndex3, PosIndex3
if (strcmp("Symmetric",ConstraintType) == 0 ) {
if (strcmp("Symmetric", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Symmetric;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(FirstPos);
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(FirstPos);
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->SecondPos = static_cast<Sketcher::PointPos>(SecondPos);
this->getConstraintPtr()->Third = ThirdIndex;
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(ThirdPos);
this->getConstraintPtr()->Third = ThirdIndex;
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(ThirdPos);
return 0;
}
}
if (PyNumber_Check(index_or_value)) { // can be float or int
if (PyNumber_Check(index_or_value)) {// can be float or int
Value = PyFloat_AsDouble(index_or_value);
if (strcmp("SnellsLaw",ConstraintType) == 0 ) {
if (strcmp("SnellsLaw", ConstraintType) == 0) {
this->getConstraintPtr()->Type = SnellsLaw;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(FirstPos);
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(FirstPos);
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->SecondPos = static_cast<Sketcher::PointPos>(SecondPos);
this->getConstraintPtr()->Third = ThirdIndex;
this->getConstraintPtr()->ThirdPos = Sketcher::PointPos::none;
this->getConstraintPtr()->Third = ThirdIndex;
this->getConstraintPtr()->ThirdPos = Sketcher::PointPos::none;
this->getConstraintPtr()->setValue(Value);
return 0;
}
@@ -476,81 +489,171 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
std::string ConstraintPy::representation() const
{
std::stringstream result;
result << "<Constraint " ;
switch(this->getConstraintPtr()->Type) {
case None : result << "'None'>";break;
case DistanceX : result << "'DistanceX'>";break;
case DistanceY : result << "'DistanceY'>";break;
case Coincident : result << "'Coincident'>";break;
case Horizontal : result << "'Horizontal' (" << getConstraintPtr()->First << ")>";break;
case Vertical : result << "'Vertical' (" << getConstraintPtr()->First << ")>";break;
case Block : result << "'Block' (" << getConstraintPtr()->First << ")>";break;
case Radius : result << "'Radius'>";break;
case Diameter : result << "'Diameter'>";break;
case Weight : result << "'Weight'>";break;
case Parallel : result << "'Parallel'>";break;
case Tangent :
result << "<Constraint ";
switch (this->getConstraintPtr()->Type) {
case None:
result << "'None'>";
break;
case DistanceX:
result << "'DistanceX'>";
break;
case DistanceY:
result << "'DistanceY'>";
break;
case Coincident:
result << "'Coincident'>";
break;
case Horizontal:
result << "'Horizontal' (" << getConstraintPtr()->First << ")>";
break;
case Vertical:
result << "'Vertical' (" << getConstraintPtr()->First << ")>";
break;
case Block:
result << "'Block' (" << getConstraintPtr()->First << ")>";
break;
case Radius:
result << "'Radius'>";
break;
case Diameter:
result << "'Diameter'>";
break;
case Weight:
result << "'Weight'>";
break;
case Parallel:
result << "'Parallel'>";
break;
case Tangent:
if (this->getConstraintPtr()->Third == GeoEnum::GeoUndef)
result << "'Tangent'>";
else
result << "'TangentViaPoint'>";
break;
case Perpendicular :
break;
case Perpendicular:
if (this->getConstraintPtr()->Third == GeoEnum::GeoUndef)
result << "'Perpendicular'>";
else
result << "'PerpendicularViaPoint'>";
break;
case Distance : result << "'Distance'>";break;
case Angle :
break;
case Distance:
result << "'Distance'>";
break;
case Angle:
if (this->getConstraintPtr()->Third == GeoEnum::GeoUndef)
result << "'Angle'>";
else
result << "'AngleViaPoint'>";
break;
case Symmetric : result << "'Symmetric'>"; break;
case SnellsLaw : result << "'SnellsLaw'>"; break;
case InternalAlignment :
switch(this->getConstraintPtr()->AlignmentType) {
case Undef : result << "'InternalAlignment:Undef'>";break;
case EllipseMajorDiameter : result << "'InternalAlignment:EllipseMajorDiameter'>";break;
case EllipseMinorDiameter : result << "'InternalAlignment:EllipseMinorDiameter'>";break;
case EllipseFocus1 : result << "'InternalAlignment:EllipseFocus1'>";break;
case EllipseFocus2 : result << "'InternalAlignment:EllipseFocus2'>";break;
default : result << "'InternalAlignment:?'>";break;
break;
case Symmetric:
result << "'Symmetric'>";
break;
case SnellsLaw:
result << "'SnellsLaw'>";
break;
case InternalAlignment:
switch (this->getConstraintPtr()->AlignmentType) {
case Undef:
result << "'InternalAlignment:Undef'>";
break;
case EllipseMajorDiameter:
result << "'InternalAlignment:EllipseMajorDiameter'>";
break;
case EllipseMinorDiameter:
result << "'InternalAlignment:EllipseMinorDiameter'>";
break;
case EllipseFocus1:
result << "'InternalAlignment:EllipseFocus1'>";
break;
case EllipseFocus2:
result << "'InternalAlignment:EllipseFocus2'>";
break;
default:
result << "'InternalAlignment:?'>";
break;
}
break;
case Equal : result << "'Equal' (" << getConstraintPtr()->First << "," << getConstraintPtr()->Second << ")>";break;
case PointOnObject : result << "'PointOnObject' (" << getConstraintPtr()->First << "," << getConstraintPtr()->Second << ")>";break;
default : result << "'?'>";break;
break;
case Equal:
result << "'Equal' (" << getConstraintPtr()->First << "," << getConstraintPtr()->Second
<< ")>";
break;
case PointOnObject:
result << "'PointOnObject' (" << getConstraintPtr()->First << ","
<< getConstraintPtr()->Second << ")>";
break;
default:
result << "'?'>";
break;
}
return result.str();
}
Py::String ConstraintPy::getType() const
{
switch(this->getConstraintPtr()->Type) {
case None : return Py::String("None");break;
case DistanceX : return Py::String("DistanceX");break;
case DistanceY : return Py::String("DistanceY");break;
case Coincident : return Py::String("Coincident");break;
case Horizontal : return Py::String("Horizontal");break;
case Vertical : return Py::String("Vertical");break;
case Block : return Py::String("Block");break;
case Radius : return Py::String("Radius");break;
case Diameter : return Py::String("Diameter");break;
case Weight : return Py::String("Weight");break;
case Parallel : return Py::String("Parallel");break;
case Tangent : return Py::String("Tangent");break;
case Perpendicular : return Py::String("Perpendicular");break;
case Distance : return Py::String("Distance");break;
case Angle : return Py::String("Angle");break;
case Symmetric : return Py::String("Symmetric"); break;
case SnellsLaw : return Py::String("SnellsLaw"); break;
case InternalAlignment : return Py::String("InternalAlignment"); break;
case Equal : return Py::String("Equal"); break;
case PointOnObject : return Py::String("PointOnObject"); break;
default : return Py::String("Undefined");break;
switch (this->getConstraintPtr()->Type) {
case None:
return Py::String("None");
break;
case DistanceX:
return Py::String("DistanceX");
break;
case DistanceY:
return Py::String("DistanceY");
break;
case Coincident:
return Py::String("Coincident");
break;
case Horizontal:
return Py::String("Horizontal");
break;
case Vertical:
return Py::String("Vertical");
break;
case Block:
return Py::String("Block");
break;
case Radius:
return Py::String("Radius");
break;
case Diameter:
return Py::String("Diameter");
break;
case Weight:
return Py::String("Weight");
break;
case Parallel:
return Py::String("Parallel");
break;
case Tangent:
return Py::String("Tangent");
break;
case Perpendicular:
return Py::String("Perpendicular");
break;
case Distance:
return Py::String("Distance");
break;
case Angle:
return Py::String("Angle");
break;
case Symmetric:
return Py::String("Symmetric");
break;
case SnellsLaw:
return Py::String("SnellsLaw");
break;
case InternalAlignment:
return Py::String("InternalAlignment");
break;
case Equal:
return Py::String("Equal");
break;
case PointOnObject:
return Py::String("PointOnObject");
break;
default:
return Py::String("Undefined");
break;
}
}
@@ -559,7 +662,7 @@ Py::Long ConstraintPy::getFirst() const
return Py::Long(this->getConstraintPtr()->First);
}
void ConstraintPy::setFirst(Py::Long arg)
void ConstraintPy::setFirst(Py::Long arg)
{
this->getConstraintPtr()->First = arg;
}
@@ -573,7 +676,8 @@ void ConstraintPy::setFirstPos(Py::Long arg)
{
int pos = arg;
if(pos>=static_cast<int>(Sketcher::PointPos::none) && pos<=static_cast<int>(Sketcher::PointPos::mid)) {
if (pos >= static_cast<int>(Sketcher::PointPos::none)
&& pos <= static_cast<int>(Sketcher::PointPos::mid)) {
this->getConstraintPtr()->FirstPos = static_cast<Sketcher::PointPos>(pos);
}
else {
@@ -589,7 +693,7 @@ Py::Long ConstraintPy::getSecond() const
return Py::Long(this->getConstraintPtr()->Second);
}
void ConstraintPy::setSecond(Py::Long arg)
void ConstraintPy::setSecond(Py::Long arg)
{
this->getConstraintPtr()->Second = arg;
}
@@ -603,7 +707,8 @@ void ConstraintPy::setSecondPos(Py::Long arg)
{
int pos = arg;
if(pos>=static_cast<int>(Sketcher::PointPos::none) && pos<=static_cast<int>(Sketcher::PointPos::mid)) {
if (pos >= static_cast<int>(Sketcher::PointPos::none)
&& pos <= static_cast<int>(Sketcher::PointPos::mid)) {
this->getConstraintPtr()->SecondPos = static_cast<Sketcher::PointPos>(pos);
}
else {
@@ -619,7 +724,7 @@ Py::Long ConstraintPy::getThird() const
return Py::Long(this->getConstraintPtr()->Third);
}
void ConstraintPy::setThird(Py::Long arg)
void ConstraintPy::setThird(Py::Long arg)
{
this->getConstraintPtr()->Third = arg;
}
@@ -633,7 +738,8 @@ void ConstraintPy::setThirdPos(Py::Long arg)
{
int pos = arg;
if(pos>=static_cast<int>(Sketcher::PointPos::none) && pos<=static_cast<int>(Sketcher::PointPos::mid)) {
if (pos >= static_cast<int>(Sketcher::PointPos::none)
&& pos <= static_cast<int>(Sketcher::PointPos::mid)) {
this->getConstraintPtr()->ThirdPos = static_cast<Sketcher::PointPos>(pos);
}
else {
@@ -649,7 +755,7 @@ Py::String ConstraintPy::getName() const
return Py::String(this->getConstraintPtr()->Name);
}
void ConstraintPy::setName(Py::String arg)
void ConstraintPy::setName(Py::String arg)
{
this->getConstraintPtr()->Name = arg;
}
@@ -674,7 +780,7 @@ Py::Boolean ConstraintPy::getIsActive() const
return Py::Boolean(this->getConstraintPtr()->isActive);
}
PyObject *ConstraintPy::getCustomAttributes(const char* /*attr*/) const
PyObject* ConstraintPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}

View File

@@ -33,19 +33,20 @@ using namespace Sketcher;
//---------- Geometry Extension
constexpr std::array<const char *, ExternalGeometryExtension::NumFlags> ExternalGeometryExtension::flag2str;
constexpr std::array<const char*, ExternalGeometryExtension::NumFlags>
ExternalGeometryExtension::flag2str;
TYPESYSTEM_SOURCE(Sketcher::ExternalGeometryExtension,Part::GeometryPersistenceExtension)
TYPESYSTEM_SOURCE(Sketcher::ExternalGeometryExtension, Part::GeometryPersistenceExtension)
void ExternalGeometryExtension::copyAttributes(Part::GeometryExtension * cpy) const
void ExternalGeometryExtension::copyAttributes(Part::GeometryExtension* cpy) const
{
Part::GeometryPersistenceExtension::copyAttributes(cpy);
static_cast<ExternalGeometryExtension *>(cpy)->Ref = this->Ref;
static_cast<ExternalGeometryExtension *>(cpy)->Flags = this->Flags;
static_cast<ExternalGeometryExtension*>(cpy)->Ref = this->Ref;
static_cast<ExternalGeometryExtension*>(cpy)->Flags = this->Flags;
}
void ExternalGeometryExtension::restoreAttributes(Base::XMLReader &reader)
void ExternalGeometryExtension::restoreAttributes(Base::XMLReader& reader)
{
Part::GeometryPersistenceExtension::restoreAttributes(reader);
@@ -53,12 +54,11 @@ void ExternalGeometryExtension::restoreAttributes(Base::XMLReader &reader)
Flags = FlagType(reader.getAttribute("Flags"));
}
void ExternalGeometryExtension::saveAttributes(Base::Writer &writer) const
void ExternalGeometryExtension::saveAttributes(Base::Writer& writer) const
{
Part::GeometryPersistenceExtension::saveAttributes(writer);
writer.Stream() << "\" Ref=\"" << Ref
<< "\" Flags=\"" << Flags.to_string();
writer.Stream() << "\" Ref=\"" << Ref << "\" Flags=\"" << Flags.to_string();
}
std::unique_ptr<Part::GeometryExtension> ExternalGeometryExtension::copy() const
@@ -67,32 +67,32 @@ std::unique_ptr<Part::GeometryExtension> ExternalGeometryExtension::copy() const
copyAttributes(cpy.get());
#if defined (__GNUC__) && (__GNUC__ <=4)
#if defined(__GNUC__) && (__GNUC__ <= 4)
return std::move(cpy);
#else
return cpy;
#endif
}
PyObject * ExternalGeometryExtension::getPyObject()
PyObject* ExternalGeometryExtension::getPyObject()
{
return new ExternalGeometryExtensionPy(new ExternalGeometryExtension(*this));
}
bool ExternalGeometryExtension::getFlagsFromName(std::string str, ExternalGeometryExtension::Flag &flag)
bool ExternalGeometryExtension::getFlagsFromName(std::string str,
ExternalGeometryExtension::Flag& flag)
{
auto pos = std::find_if( ExternalGeometryExtension::flag2str.begin(),
ExternalGeometryExtension::flag2str.end(),
[str](const char * val) {
return strcmp(val,str.c_str())==0;
}
);
auto pos = std::find_if(ExternalGeometryExtension::flag2str.begin(),
ExternalGeometryExtension::flag2str.end(),
[str](const char* val) {
return strcmp(val, str.c_str()) == 0;
});
if( pos != ExternalGeometryExtension::flag2str.end()) {
int index = std::distance( ExternalGeometryExtension::flag2str.begin(), pos );
if (pos != ExternalGeometryExtension::flag2str.end()) {
int index = std::distance(ExternalGeometryExtension::flag2str.begin(), pos);
flag = static_cast<ExternalGeometryExtension::Flag>(index);
return true;
flag = static_cast<ExternalGeometryExtension::Flag>(index);
return true;
}
return false;

View File

@@ -37,75 +37,103 @@ class ISketchExternalGeometryExtension
{
public:
// Identification information
// START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) <realthunder.dev@gmail.com>
// START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder)
// <realthunder.dev@gmail.com>
virtual bool testFlag(int flag) const = 0;
virtual void setFlag(int flag, bool v=true) = 0;
// END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) <realthunder.dev@gmail.com>
virtual void setFlag(int flag, bool v = true) = 0;
// END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder)
// <realthunder.dev@gmail.com>
virtual bool isClear() const = 0;
virtual size_t flagSize() const = 0;
virtual const std::string& getRef() const = 0;
virtual void setRef(const std::string & ref) = 0;
virtual void setRef(const std::string& ref) = 0;
};
class SketcherExport ExternalGeometryExtension : public Part::GeometryPersistenceExtension, private ISketchExternalGeometryExtension
class SketcherExport ExternalGeometryExtension: public Part::GeometryPersistenceExtension,
private ISketchExternalGeometryExtension
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
// START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) <realthunder.dev@gmail.com>
enum Flag {
Defining = 0, // allow an external geometry to build shape
Frozen = 1, // freeze an external geometry
Detached = 2, // signal the intentions of detaching the geometry from external reference
Missing = 3, // geometry with missing external reference
Sync = 4, // signal the intention to synchronize a frozen geometry
NumFlags // Must be the last type
// START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder)
// <realthunder.dev@gmail.com>
enum Flag
{
Defining = 0,// allow an external geometry to build shape
Frozen = 1, // freeze an external geometry
Detached = 2,// signal the intentions of detaching the geometry from external reference
Missing = 3, // geometry with missing external reference
Sync = 4, // signal the intention to synchronize a frozen geometry
NumFlags // Must be the last type
};
// END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) <realthunder.dev@gmail.com>
// END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder)
// <realthunder.dev@gmail.com>
constexpr static std::array<const char*, NumFlags> flag2str {
{"Defining", "Frozen", "Detached", "Missing", "Sync"}};
constexpr static std::array<const char *,NumFlags> flag2str {{ "Defining", "Frozen", "Detached","Missing", "Sync" }};
public:
ExternalGeometryExtension() = default;
~ExternalGeometryExtension() override = default;
std::unique_ptr<Part::GeometryExtension> copy() const override;
PyObject *getPyObject() override;
PyObject* getPyObject() override;
// START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) <realthunder.dev@gmail.com>
bool testFlag(int flag) const override { return Flags.test((size_t)(flag)); }
void setFlag(int flag, bool v=true) override { Flags.set((size_t)(flag),v); }
// END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) <realthunder.dev@gmail.com>
// START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder)
// <realthunder.dev@gmail.com>
bool testFlag(int flag) const override
{
return Flags.test((size_t)(flag));
}
void setFlag(int flag, bool v = true) override
{
Flags.set((size_t)(flag), v);
}
// END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder)
// <realthunder.dev@gmail.com>
bool isClear() const override {return Flags.none();}
size_t flagSize() const override {return Flags.size();}
bool isClear() const override
{
return Flags.none();
}
size_t flagSize() const override
{
return Flags.size();
}
const std::string& getRef() const override {return Ref;}
void setRef(const std::string & ref) override {Ref = ref;}
const std::string& getRef() const override
{
return Ref;
}
void setRef(const std::string& ref) override
{
Ref = ref;
}
static bool getFlagsFromName(std::string str, ExternalGeometryExtension::Flag &flag);
static bool getFlagsFromName(std::string str, ExternalGeometryExtension::Flag& flag);
protected:
void copyAttributes(Part::GeometryExtension * cpy) const override;
void restoreAttributes(Base::XMLReader &reader) override;
void saveAttributes(Base::Writer &writer) const override;
void copyAttributes(Part::GeometryExtension* cpy) const override;
void restoreAttributes(Base::XMLReader& reader) override;
void saveAttributes(Base::Writer& writer) const override;
private:
ExternalGeometryExtension(const ExternalGeometryExtension&) = default;
private:
using FlagType = std::bitset<32>;
// START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) <realthunder.dev@gmail.com>
// START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder)
// <realthunder.dev@gmail.com>
std::string Ref;
FlagType Flags;
// END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) <realthunder.dev@gmail.com>
// END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder)
// <realthunder.dev@gmail.com>
};
} //namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_EXTERNALGEOMETRYEXTENSION_H
#endif// SKETCHER_EXTERNALGEOMETRYEXTENSION_H

View File

@@ -23,6 +23,7 @@
#include "PreCompiled.h"
#include "ExternalGeometryExtensionPy.h"
#include "ExternalGeometryExtensionPy.cpp"
@@ -36,23 +37,22 @@ std::string ExternalGeometryExtensionPy::representation() const
std::string ref = getExternalGeometryExtensionPtr()->getRef();
str << "<ExternalGeometryExtension (";
if(!getExternalGeometryExtensionPtr()->getName().empty())
if (!getExternalGeometryExtensionPtr()->getName().empty())
str << "\'" << getExternalGeometryExtensionPtr()->getName() << "\', ";
str << "\"" << ref;
if(!getExternalGeometryExtensionPtr()->isClear()) {
str<< "\",{";
if (!getExternalGeometryExtensionPtr()->isClear()) {
str << "\",{";
bool first=true;
bool first = true;
for(size_t i=0;i<ExternalGeometryExtension::NumFlags;i++) {
if(getExternalGeometryExtensionPtr()->testFlag(i)) {
if(first) {
first=false;
for (size_t i = 0; i < ExternalGeometryExtension::NumFlags; i++) {
if (getExternalGeometryExtensionPtr()->testFlag(i)) {
if (first) {
first = false;
}
else {
str << ", ";
@@ -62,7 +62,7 @@ std::string ExternalGeometryExtensionPy::representation() const
}
}
str<< "}";
str << "}";
}
else {
str << "\") >";
@@ -73,7 +73,8 @@ std::string ExternalGeometryExtensionPy::representation() const
return str.str();
}
PyObject *ExternalGeometryExtensionPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
// Python wrapper
PyObject* ExternalGeometryExtensionPy::PyMake(struct _typeobject*, PyObject*, PyObject*)
{
// create a new instance of PointPy and the Twin object
return new ExternalGeometryExtensionPy(new ExternalGeometryExtension);
@@ -88,39 +89,40 @@ int ExternalGeometryExtensionPy::PyInit(PyObject* args, PyObject* /*kwd*/)
return 0;
}
PyErr_SetString(PyExc_TypeError, "ExternalGeometryExtension constructor accepts:\n"
"-- empty parameter list\n");
PyErr_SetString(PyExc_TypeError,
"ExternalGeometryExtension constructor accepts:\n"
"-- empty parameter list\n");
return -1;
}
PyObject* ExternalGeometryExtensionPy::testFlag(PyObject *args)
PyObject* ExternalGeometryExtensionPy::testFlag(PyObject* args)
{
char* flag;
if (PyArg_ParseTuple(args, "s",&flag)) {
if (PyArg_ParseTuple(args, "s", &flag)) {
ExternalGeometryExtension::Flag flagtype;
if(getExternalGeometryExtensionPtr()->getFlagsFromName(flag, flagtype))
return new_reference_to(Py::Boolean(this->getExternalGeometryExtensionPtr()->testFlag(flagtype)));
if (getExternalGeometryExtensionPtr()->getFlagsFromName(flag, flagtype))
return new_reference_to(
Py::Boolean(this->getExternalGeometryExtensionPtr()->testFlag(flagtype)));
PyErr_SetString(PyExc_TypeError, "Flag string does not exist.");
return nullptr;
}
PyErr_SetString(PyExc_TypeError, "No flag string provided.");
return nullptr;
}
PyObject* ExternalGeometryExtensionPy::setFlag(PyObject *args)
PyObject* ExternalGeometryExtensionPy::setFlag(PyObject* args)
{
char * flag;
PyObject * bflag = Py_True;
char* flag;
PyObject* bflag = Py_True;
if (PyArg_ParseTuple(args, "s|O!", &flag, &PyBool_Type, &bflag)) {
ExternalGeometryExtension::Flag flagtype;
if(getExternalGeometryExtensionPtr()->getFlagsFromName(flag, flagtype)) {
if (getExternalGeometryExtensionPtr()->getFlagsFromName(flag, flagtype)) {
this->getExternalGeometryExtensionPtr()->setFlag(flagtype, Base::asBoolean(bflag));
Py_Return;
@@ -145,7 +147,7 @@ void ExternalGeometryExtensionPy::setRef(Py::String value)
}
PyObject *ExternalGeometryExtensionPy::getCustomAttributes(const char* /*attr*/) const
PyObject* ExternalGeometryExtensionPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}

View File

@@ -22,7 +22,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_io.hpp>
#endif
#include <Base/Console.h>
@@ -33,43 +33,45 @@
using namespace Sketcher;
TYPESYSTEM_SOURCE(Sketcher::ExternalGeometryFacade,Base::BaseClass)
TYPESYSTEM_SOURCE(Sketcher::ExternalGeometryFacade, Base::BaseClass)
ExternalGeometryFacade::ExternalGeometryFacade(): Geo(nullptr), SketchGeoExtension(nullptr), ExternalGeoExtension(nullptr)
ExternalGeometryFacade::ExternalGeometryFacade()
: Geo(nullptr),
SketchGeoExtension(nullptr),
ExternalGeoExtension(nullptr)
{}
ExternalGeometryFacade::ExternalGeometryFacade(const Part::Geometry* geometry)
: Geo(geometry)
{
}
ExternalGeometryFacade::ExternalGeometryFacade(const Part::Geometry * geometry)
: Geo(geometry)
{
if(geometry)
if (geometry)
initExtensions();
else
THROWM(Base::ValueError, "ExternalGeometryFacade initialized with Geometry null pointer");
}
std::unique_ptr<ExternalGeometryFacade> ExternalGeometryFacade::getFacade(Part::Geometry * geometry)
std::unique_ptr<ExternalGeometryFacade> ExternalGeometryFacade::getFacade(Part::Geometry* geometry)
{
if(geometry)
if (geometry)
return std::unique_ptr<ExternalGeometryFacade>(new ExternalGeometryFacade(geometry));
else
else
return std::unique_ptr<ExternalGeometryFacade>(nullptr);
}
std::unique_ptr<const ExternalGeometryFacade> ExternalGeometryFacade::getFacade(const Part::Geometry * geometry)
std::unique_ptr<const ExternalGeometryFacade>
ExternalGeometryFacade::getFacade(const Part::Geometry* geometry)
{
if(geometry)
if (geometry)
return std::unique_ptr<const ExternalGeometryFacade>(new ExternalGeometryFacade(geometry));
else
else
return std::unique_ptr<const ExternalGeometryFacade>(nullptr);
}
void ExternalGeometryFacade::setGeometry(Part::Geometry *geometry)
void ExternalGeometryFacade::setGeometry(Part::Geometry* geometry)
{
Geo = geometry;
if(geometry)
if (geometry)
initExtensions();
else
THROWM(Base::ValueError, "ExternalGeometryFacade initialized with Geometry null pointer");
@@ -77,67 +79,72 @@ void ExternalGeometryFacade::setGeometry(Part::Geometry *geometry)
void ExternalGeometryFacade::initExtensions()
{
if(!Geo->hasExtension(SketchGeometryExtension::getClassTypeId())) {
if (!Geo->hasExtension(SketchGeometryExtension::getClassTypeId())) {
getGeo()->setExtension(std::make_unique<SketchGeometryExtension>()); // Create getExtension
getGeo()->setExtension(std::make_unique<SketchGeometryExtension>());// Create getExtension
Base::Console().Warning("%s\nSketcher External Geometry without Geometry Extension: %s \n", boost::uuids::to_string(Geo->getTag()).c_str());
Base::Console().Warning("%s\nSketcher External Geometry without Geometry Extension: %s \n",
boost::uuids::to_string(Geo->getTag()).c_str());
}
if(!Geo->hasExtension(ExternalGeometryExtension::getClassTypeId())) {
if (!Geo->hasExtension(ExternalGeometryExtension::getClassTypeId())) {
getGeo()->setExtension(std::make_unique<ExternalGeometryExtension>()); // Create getExtension
getGeo()->setExtension(std::make_unique<ExternalGeometryExtension>());// Create getExtension
Base::Console().Warning("%s\nSketcher External Geometry without ExternalGeometryExtension: %s \n", boost::uuids::to_string(Geo->getTag()).c_str());
Base::Console().Warning(
"%s\nSketcher External Geometry without ExternalGeometryExtension: %s \n",
boost::uuids::to_string(Geo->getTag()).c_str());
}
SketchGeoExtension =
std::static_pointer_cast<const SketchGeometryExtension>(
(Geo->getExtension(SketchGeometryExtension::getClassTypeId())).lock()
);
SketchGeoExtension = std::static_pointer_cast<const SketchGeometryExtension>(
(Geo->getExtension(SketchGeometryExtension::getClassTypeId())).lock());
ExternalGeoExtension =
std::static_pointer_cast<const ExternalGeometryExtension>(
(Geo->getExtension(ExternalGeometryExtension::getClassTypeId())).lock()
);
ExternalGeoExtension = std::static_pointer_cast<const ExternalGeometryExtension>(
(Geo->getExtension(ExternalGeometryExtension::getClassTypeId())).lock());
}
void ExternalGeometryFacade::initExtensions() const
{
if(!Geo->hasExtension(SketchGeometryExtension::getClassTypeId()))
THROWM(Base::ValueError, "ExternalGeometryFacade for const::Geometry without SketchGeometryExtension");
if (!Geo->hasExtension(SketchGeometryExtension::getClassTypeId()))
THROWM(Base::ValueError,
"ExternalGeometryFacade for const::Geometry without SketchGeometryExtension");
if(!Geo->hasExtension(ExternalGeometryExtension::getClassTypeId()))
THROWM(Base::ValueError, "ExternalGeometryFacade for const::Geometry without ExternalGeometryExtension");
if (!Geo->hasExtension(ExternalGeometryExtension::getClassTypeId()))
THROWM(Base::ValueError,
"ExternalGeometryFacade for const::Geometry without ExternalGeometryExtension");
auto ext = std::static_pointer_cast<const SketchGeometryExtension>(Geo->getExtension(SketchGeometryExtension::getClassTypeId()).lock());
auto ext = std::static_pointer_cast<const SketchGeometryExtension>(
Geo->getExtension(SketchGeometryExtension::getClassTypeId()).lock());
const_cast<ExternalGeometryFacade *>(this)->SketchGeoExtension = ext;
const_cast<ExternalGeometryFacade*>(this)->SketchGeoExtension = ext;
auto extext = std::static_pointer_cast<const ExternalGeometryExtension>(Geo->getExtension(ExternalGeometryExtension::getClassTypeId()).lock());
auto extext = std::static_pointer_cast<const ExternalGeometryExtension>(
Geo->getExtension(ExternalGeometryExtension::getClassTypeId()).lock());
const_cast<ExternalGeometryFacade *>(this)->ExternalGeoExtension = extext;
const_cast<ExternalGeometryFacade*>(this)->ExternalGeoExtension = extext;
}
void ExternalGeometryFacade::ensureSketchGeometryExtensions(Part::Geometry * geometry)
void ExternalGeometryFacade::ensureSketchGeometryExtensions(Part::Geometry* geometry)
{
if(!geometry->hasExtension(SketchGeometryExtension::getClassTypeId())) {
geometry->setExtension(std::make_unique<SketchGeometryExtension>()); // Create geoExtension
if (!geometry->hasExtension(SketchGeometryExtension::getClassTypeId())) {
// Create geoExtension
geometry->setExtension(std::make_unique<SketchGeometryExtension>());
}
if(!geometry->hasExtension(ExternalGeometryExtension::getClassTypeId())) {
geometry->setExtension(std::make_unique<ExternalGeometryExtension>()); // Create external geoExtension
if (!geometry->hasExtension(ExternalGeometryExtension::getClassTypeId())) {
// Create external geoExtension
geometry->setExtension(std::make_unique<ExternalGeometryExtension>());
}
}
void ExternalGeometryFacade::copyId(const Part::Geometry * src, Part::Geometry * dst)
void ExternalGeometryFacade::copyId(const Part::Geometry* src, Part::Geometry* dst)
{
auto gfsrc = ExternalGeometryFacade::getFacade(src);
auto gfdst = ExternalGeometryFacade::getFacade(dst);
gfdst->setId(gfsrc->getId());
}
PyObject * ExternalGeometryFacade::getPyObject()
PyObject* ExternalGeometryFacade::getPyObject()
{
return new ExternalGeometryFacadePy(new ExternalGeometryFacade(this->Geo));
}

View File

@@ -34,137 +34,277 @@ namespace Sketcher
{
class ExternalGeometryFacadePy;
// This class is a Facade to handle EXTERNAL sketcher geometry and sketcher geometry extensions with a single sketcher specific interface.
// This class is a Facade to handle EXTERNAL sketcher geometry and sketcher geometry extensions with
// a single sketcher specific interface.
//
// Exactly the same considerations as for GeometryFacade apply (see documentation of GeometryFacade).
// Exactly the same considerations as for GeometryFacade apply (see documentation of
// GeometryFacade).
//
// It was not made publicly deriving from GeometryFacade because it is not possible to differentiate functions by return type, which is the
// case of getFacade() returning a unique_ptr to GeometryFacade in GeometryFacade, and one to ExternalGeometryFacade. I have not managed to
// find a good solution to this problem, thus the code duplication.
// It was not made publicly deriving from GeometryFacade because it is not possible to differentiate
// functions by return type, which is the case of getFacade() returning a unique_ptr to
// GeometryFacade in GeometryFacade, and one to ExternalGeometryFacade. I have not managed to find a
// good solution to this problem, thus the code duplication.
//
// Summary Remarks:
// It is intended to have a separate type (not being a Geometry type).
// it is intended to have the relevant interface in full for the sketcher extension only
// It is intended to work on borrowed memory allocation.
class SketcherExport ExternalGeometryFacade : public Base::BaseClass, private ISketchGeometryExtension, private ISketchExternalGeometryExtension
class SketcherExport ExternalGeometryFacade: public Base::BaseClass,
private ISketchGeometryExtension,
private ISketchExternalGeometryExtension
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER_WITH_OVERRIDE();
private:
explicit ExternalGeometryFacade(const Part::Geometry * geometry);
ExternalGeometryFacade(); // As TYPESYSTEM requirement
explicit ExternalGeometryFacade(const Part::Geometry* geometry);
ExternalGeometryFacade();// As TYPESYSTEM requirement
friend class ExternalGeometryFacadePy;
public: // Factory methods
static std::unique_ptr<ExternalGeometryFacade> getFacade(Part::Geometry * geometry);
static std::unique_ptr<const ExternalGeometryFacade> getFacade(const Part::Geometry * geometry);
public:// Factory methods
static std::unique_ptr<ExternalGeometryFacade> getFacade(Part::Geometry* geometry);
static std::unique_ptr<const ExternalGeometryFacade> getFacade(const Part::Geometry* geometry);
public: // Utility methods
static void ensureSketchGeometryExtensions(Part::Geometry * geometry);
static void copyId(const Part::Geometry * src, Part::Geometry * dst);
public:// Utility methods
static void ensureSketchGeometryExtensions(Part::Geometry* geometry);
static void copyId(const Part::Geometry* src, Part::Geometry* dst);
public:
void setGeometry(Part::Geometry *geometry);
void setGeometry(Part::Geometry* geometry);
/** External GeometryExtension Interface **/
bool testFlag(int flag) const override { return getExternalGeoExt()->testFlag(flag); }
void setFlag(int flag, bool v=true) override { getExternalGeoExt()->setFlag(flag, v); }
bool testFlag(int flag) const override
{
return getExternalGeoExt()->testFlag(flag);
}
void setFlag(int flag, bool v = true) override
{
getExternalGeoExt()->setFlag(flag, v);
}
bool isClear() const override {return getExternalGeoExt()->isClear();}
size_t flagSize() const override {return getExternalGeoExt()->flagSize();}
bool isClear() const override
{
return getExternalGeoExt()->isClear();
}
size_t flagSize() const override
{
return getExternalGeoExt()->flagSize();
}
const std::string& getRef() const override {return getExternalGeoExt()->getRef();}
void setRef(const std::string & ref) override {getExternalGeoExt()->setRef(ref);}
const std::string& getRef() const override
{
return getExternalGeoExt()->getRef();
}
void setRef(const std::string& ref) override
{
getExternalGeoExt()->setRef(ref);
}
/** GeometryExtension Interface **/
inline long getId() const override {return getGeoExt()->getId();}
void setId(long id) override {getGeoExt()->setId(id);}
inline long getId() const override
{
return getGeoExt()->getId();
}
void setId(long id) override
{
getGeoExt()->setId(id);
}
InternalType::InternalType getInternalType() const override {return getGeoExt()->getInternalType();}
void setInternalType(InternalType::InternalType type) override {getGeoExt()->setInternalType(type);}
InternalType::InternalType getInternalType() const override
{
return getGeoExt()->getInternalType();
}
void setInternalType(InternalType::InternalType type) override
{
getGeoExt()->setInternalType(type);
}
bool testGeometryMode(int flag) const override { return getGeoExt()->testGeometryMode(flag); }
void setGeometryMode(int flag, bool v=true) override { getGeoExt()->setGeometryMode(flag, v); }
bool testGeometryMode(int flag) const override
{
return getGeoExt()->testGeometryMode(flag);
}
void setGeometryMode(int flag, bool v = true) override
{
getGeoExt()->setGeometryMode(flag, v);
}
int getGeometryLayerId() const override { return getGeoExt()->getGeometryLayerId();}
void setGeometryLayerId(int geolayer) override { getGeoExt()->setGeometryLayerId(geolayer);}
int getGeometryLayerId() const override
{
return getGeoExt()->getGeometryLayerId();
}
void setGeometryLayerId(int geolayer) override
{
getGeoExt()->setGeometryLayerId(geolayer);
}
// Convenience accessor
bool getBlocked() const { return this->testGeometryMode(GeometryMode::Blocked);}
void setBlocked(bool status = true) {this->setGeometryMode(GeometryMode::Blocked, status);}
bool getBlocked() const
{
return this->testGeometryMode(GeometryMode::Blocked);
}
void setBlocked(bool status = true)
{
this->setGeometryMode(GeometryMode::Blocked, status);
}
inline bool getConstruction() const {return this->testGeometryMode(GeometryMode::Construction);};
inline void setConstruction(bool construction) {this->setGeometryMode(GeometryMode::Construction, construction);};
inline bool getConstruction() const
{
return this->testGeometryMode(GeometryMode::Construction);
};
inline void setConstruction(bool construction)
{
this->setGeometryMode(GeometryMode::Construction, construction);
};
// Geometry Extension Information
inline const std::string &getSketchExtensionName () const {return SketchGeoExtension->getName();}
inline const std::string &getExternalExtensionName () const {return ExternalGeoExtension->getName();}
inline const std::string& getSketchExtensionName() const
{
return SketchGeoExtension->getName();
}
inline const std::string& getExternalExtensionName() const
{
return ExternalGeoExtension->getName();
}
// Geometry Element
template < typename GeometryT = Part::Geometry,
typename = typename std::enable_if<
std::is_base_of<Part::Geometry, typename std::decay<GeometryT>::type>::value
>::type
>
GeometryT * getGeometry() {return dynamic_cast<GeometryT *>(const_cast<GeometryT *>(Geo));}
template<typename GeometryT = Part::Geometry,
typename = typename std::enable_if<std::is_base_of<
Part::Geometry, typename std::decay<GeometryT>::type>::value>::type>
GeometryT* getGeometry()
{
return dynamic_cast<GeometryT*>(const_cast<GeometryT*>(Geo));
}
// Geometry Element
template < typename GeometryT = Part::Geometry,
typename = typename std::enable_if<
std::is_base_of<Part::Geometry, typename std::decay<GeometryT>::type>::value
>::type
>
GeometryT * getGeometry() const {return dynamic_cast<GeometryT *>(Geo);}
template<typename GeometryT = Part::Geometry,
typename = typename std::enable_if<std::is_base_of<
Part::Geometry, typename std::decay<GeometryT>::type>::value>::type>
GeometryT* getGeometry() const
{
return dynamic_cast<GeometryT*>(Geo);
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
/** Geometry Interface **/
TopoDS_Shape toShape() const {return getGeo()->toShape();};
const Handle(Geom_Geometry)& handle() const {return getGeo()->handle();};
Part::Geometry *copy() const {return getGeo()->copy();};
Part::Geometry *clone() const {return getGeo()->clone();};
boost::uuids::uuid getTag() const {return getGeo()->getTag();};
TopoDS_Shape toShape() const
{
return getGeo()->toShape();
};
const Handle(Geom_Geometry) & handle() const
{
return getGeo()->handle();
};
Part::Geometry* copy() const
{
return getGeo()->copy();
};
Part::Geometry* clone() const
{
return getGeo()->clone();
};
boost::uuids::uuid getTag() const
{
return getGeo()->getTag();
};
std::vector<std::weak_ptr<const Part::GeometryExtension>> getExtensions() const {return getGeo()->getExtensions();};
bool hasExtension(Base::Type type) const {return getGeo()->hasExtension(type);};
bool hasExtension(const std::string & name) const {return getGeo()->hasExtension(name);};
std::weak_ptr<const Part::GeometryExtension> getExtension(Base::Type type) const {return getGeo()->getExtension(type);};
std::weak_ptr<const Part::GeometryExtension> getExtension(const std::string & name) const {return getGeo()->getExtension(name);};
void setExtension(std::unique_ptr<Part::GeometryExtension> &&geo) {return getGeo()->setExtension(std::move(geo));};
void deleteExtension(Base::Type type) {return getGeo()->deleteExtension(type);};
void deleteExtension(const std::string & name) {return getGeo()->deleteExtension(name);};
std::vector<std::weak_ptr<const Part::GeometryExtension>> getExtensions() const
{
return getGeo()->getExtensions();
};
bool hasExtension(Base::Type type) const
{
return getGeo()->hasExtension(type);
};
bool hasExtension(const std::string& name) const
{
return getGeo()->hasExtension(name);
};
std::weak_ptr<const Part::GeometryExtension> getExtension(Base::Type type) const
{
return getGeo()->getExtension(type);
};
std::weak_ptr<const Part::GeometryExtension> getExtension(const std::string& name) const
{
return getGeo()->getExtension(name);
};
void setExtension(std::unique_ptr<Part::GeometryExtension>&& geo)
{
return getGeo()->setExtension(std::move(geo));
};
void deleteExtension(Base::Type type)
{
return getGeo()->deleteExtension(type);
};
void deleteExtension(const std::string& name)
{
return getGeo()->deleteExtension(name);
};
void mirror(const Base::Vector3d & point) {return getGeo()->mirror(point);};
void mirror(const Base::Vector3d & point, Base::Vector3d dir) {return getGeo()->mirror(point, dir);};
void rotate(const Base::Placement & plm) {return getGeo()->rotate(plm);};
void scale(const Base::Vector3d & vec, double scale) {return getGeo()->scale(vec, scale);};
void transform(const Base::Matrix4D & mat) {return getGeo()->transform(mat);};
void translate(const Base::Vector3d & vec) {return getGeo()->translate(vec);};
void mirror(const Base::Vector3d& point)
{
return getGeo()->mirror(point);
};
void mirror(const Base::Vector3d& point, Base::Vector3d dir)
{
return getGeo()->mirror(point, dir);
};
void rotate(const Base::Placement& plm)
{
return getGeo()->rotate(plm);
};
void scale(const Base::Vector3d& vec, double scale)
{
return getGeo()->scale(vec, scale);
};
void transform(const Base::Matrix4D& mat)
{
return getGeo()->transform(mat);
};
void translate(const Base::Vector3d& vec)
{
return getGeo()->translate(vec);
};
private:
void initExtensions();
void initExtensions() const;
const Part::Geometry * getGeo() const {return Geo;}
Part::Geometry * getGeo() {return const_cast<Part::Geometry *>(Geo);}
const Part::Geometry* getGeo() const
{
return Geo;
}
Part::Geometry* getGeo()
{
return const_cast<Part::Geometry*>(Geo);
}
std::shared_ptr<const SketchGeometryExtension> getGeoExt() const {return SketchGeoExtension;}
std::shared_ptr<SketchGeometryExtension> getGeoExt () {return std::const_pointer_cast<SketchGeometryExtension>(SketchGeoExtension);}
std::shared_ptr<const SketchGeometryExtension> getGeoExt() const
{
return SketchGeoExtension;
}
std::shared_ptr<SketchGeometryExtension> getGeoExt()
{
return std::const_pointer_cast<SketchGeometryExtension>(SketchGeoExtension);
}
std::shared_ptr<const ExternalGeometryExtension> getExternalGeoExt() const {return ExternalGeoExtension;}
std::shared_ptr<ExternalGeometryExtension> getExternalGeoExt () {return std::const_pointer_cast<ExternalGeometryExtension>(ExternalGeoExtension);}
std::shared_ptr<const ExternalGeometryExtension> getExternalGeoExt() const
{
return ExternalGeoExtension;
}
std::shared_ptr<ExternalGeometryExtension> getExternalGeoExt()
{
return std::const_pointer_cast<ExternalGeometryExtension>(ExternalGeoExtension);
}
private:
const Part::Geometry * Geo;
const Part::Geometry* Geo;
std::shared_ptr<const SketchGeometryExtension> SketchGeoExtension;
std::shared_ptr<const ExternalGeometryExtension> ExternalGeoExtension;
};
}// namespace Sketcher
} //namespace Sketcher
#endif // SKETCHER_GEOMETRYEXTERNALFACADE_H
#endif// SKETCHER_GEOMETRYEXTERNALFACADE_H

View File

@@ -27,11 +27,12 @@
#include <Base/PlacementPy.h>
#include <Base/Vector3D.h>
#include <Base/VectorPy.h>
#include <Mod/Part/App/GeometryPy.h>
#include <Mod/Part/App/GeometryExtensionPy.h>
#include <Mod/Part/App/GeometryPy.h>
#include <Mod/Part/App/OCCError.h>
#include "ExternalGeometryFacadePy.h"
#include "ExternalGeometryFacadePy.cpp"
@@ -47,7 +48,8 @@ std::string ExternalGeometryFacadePy::representation() const
return str.str();
}
PyObject *ExternalGeometryFacadePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
PyObject* ExternalGeometryFacadePy::PyMake(struct _typeobject*, PyObject*,
PyObject*)// Python wrapper
{
// create a new instance of PointPy and the Twin object
return new ExternalGeometryFacadePy(new ExternalGeometryFacade());
@@ -56,60 +58,61 @@ PyObject *ExternalGeometryFacadePy::PyMake(struct _typeobject *, PyObject *, PyO
// constructor method
int ExternalGeometryFacadePy::PyInit(PyObject* args, PyObject* /*kwd*/)
{
PyObject *object;
if (PyArg_ParseTuple(args,"O!",&(Part::GeometryPy::Type), &object)) {
Part::Geometry * geo = static_cast<Part::GeometryPy *>(object)->getGeometryPtr();
PyObject* object;
if (PyArg_ParseTuple(args, "O!", &(Part::GeometryPy::Type), &object)) {
Part::Geometry* geo = static_cast<Part::GeometryPy*>(object)->getGeometryPtr();
getExternalGeometryFacadePtr()->setGeometry(geo->clone());
return 0;
}
PyErr_SetString(PyExc_TypeError, "Sketcher::ExternalGeometryFacade constructor accepts:\n"
"-- Part.Geometry\n"
);
PyErr_SetString(PyExc_TypeError,
"Sketcher::ExternalGeometryFacade constructor accepts:\n"
"-- Part.Geometry\n");
return -1;
}
PyObject* ExternalGeometryFacadePy::testFlag(PyObject *args)
PyObject* ExternalGeometryFacadePy::testFlag(PyObject* args)
{
char* flag;
if (PyArg_ParseTuple(args, "s",&flag)) {
if (PyArg_ParseTuple(args, "s", &flag)) {
auto pos = std::find_if(ExternalGeometryExtension::flag2str.begin(),
ExternalGeometryExtension::flag2str.end(),
[flag](const char * val) { return strcmp(val,flag) == 0;});
ExternalGeometryExtension::flag2str.end(),
[flag](const char* val) {
return strcmp(val, flag) == 0;
});
if( pos != ExternalGeometryExtension::flag2str.end()) {
int index = std::distance( ExternalGeometryExtension::flag2str.begin(), pos );
if (pos != ExternalGeometryExtension::flag2str.end()) {
int index = std::distance(ExternalGeometryExtension::flag2str.begin(), pos);
return new_reference_to(Py::Boolean(this->getExternalGeometryFacadePtr()->testFlag(index)));
return new_reference_to(
Py::Boolean(this->getExternalGeometryFacadePtr()->testFlag(index)));
}
PyErr_SetString(PyExc_TypeError, "Flag string does not exist.");
return nullptr;
}
PyErr_SetString(PyExc_TypeError, "No flag string provided.");
return nullptr;
}
PyObject* ExternalGeometryFacadePy::setFlag(PyObject *args)
PyObject* ExternalGeometryFacadePy::setFlag(PyObject* args)
{
char * flag;
PyObject * bflag = Py_True;
char* flag;
PyObject* bflag = Py_True;
if (PyArg_ParseTuple(args, "s|O!", &flag, &PyBool_Type, &bflag)) {
auto pos = std::find_if(ExternalGeometryExtension::flag2str.begin(),
ExternalGeometryExtension::flag2str.end(),
[flag](const char * val) {
return strcmp(val,flag)==0;
}
);
[flag](const char* val) {
return strcmp(val, flag) == 0;
});
if( pos != ExternalGeometryExtension::flag2str.end()) {
int index = std::distance( ExternalGeometryExtension::flag2str.begin(), pos );
if (pos != ExternalGeometryExtension::flag2str.end()) {
int index = std::distance(ExternalGeometryExtension::flag2str.begin(), pos);
this->getExternalGeometryFacadePtr()->setFlag(index, Base::asBoolean(bflag));
Py_Return;
@@ -147,12 +150,12 @@ Py::String ExternalGeometryFacadePy::getInternalType() const
{
int internaltypeindex = (int)this->getExternalGeometryFacadePtr()->getInternalType();
if(internaltypeindex >= InternalType::NumInternalGeometryType)
if (internaltypeindex >= InternalType::NumInternalGeometryType)
throw Py::NotImplementedError("String name of enum not implemented");
std::string typestr = SketchGeometryExtension::internaltype2str[internaltypeindex];
return Py::String(typestr);
return Py::String(typestr);
}
void ExternalGeometryFacadePy::setInternalType(Py::String arg)
@@ -160,7 +163,7 @@ void ExternalGeometryFacadePy::setInternalType(Py::String arg)
std::string argstr = arg;
InternalType::InternalType type;
if(SketchGeometryExtension::getInternalTypeFromName(argstr, type)) {
if (SketchGeometryExtension::getInternalTypeFromName(argstr, type)) {
this->getExternalGeometryFacadePtr()->setInternalType(type);
return;
}
@@ -178,10 +181,10 @@ void ExternalGeometryFacadePy::setBlocked(Py::Boolean arg)
getExternalGeometryFacadePtr()->setBlocked(arg);
}
PyObject* ExternalGeometryFacadePy::mirror(PyObject *args)
PyObject* ExternalGeometryFacadePy::mirror(PyObject* args)
{
PyObject* o;
if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&o)) {
if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &o)) {
Base::Vector3d vec = static_cast<Base::VectorPy*>(o)->value();
getExternalGeometryFacadePtr()->mirror(vec);
Py_Return;
@@ -189,22 +192,23 @@ PyObject* ExternalGeometryFacadePy::mirror(PyObject *args)
PyErr_Clear();
PyObject* axis;
if (PyArg_ParseTuple(args, "O!O!", &(Base::VectorPy::Type),&o,
&(Base::VectorPy::Type),&axis)) {
if (PyArg_ParseTuple(
args, "O!O!", &(Base::VectorPy::Type), &o, &(Base::VectorPy::Type), &axis)) {
Base::Vector3d pnt = static_cast<Base::VectorPy*>(o)->value();
Base::Vector3d dir = static_cast<Base::VectorPy*>(axis)->value();
getExternalGeometryFacadePtr()->mirror(pnt, dir);
Py_Return;
}
PyErr_SetString(Part::PartExceptionOCCError, "either a point (vector) or axis (vector, vector) must be given");
PyErr_SetString(Part::PartExceptionOCCError,
"either a point (vector) or axis (vector, vector) must be given");
return nullptr;
}
PyObject* ExternalGeometryFacadePy::rotate(PyObject *args)
PyObject* ExternalGeometryFacadePy::rotate(PyObject* args)
{
PyObject* o;
if (!PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type),&o))
if (!PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &o))
return nullptr;
Base::Placement* plm = static_cast<Base::PlacementPy*>(o)->getPlacementPtr();
@@ -212,19 +216,19 @@ PyObject* ExternalGeometryFacadePy::rotate(PyObject *args)
Py_Return;
}
PyObject* ExternalGeometryFacadePy::scale(PyObject *args)
PyObject* ExternalGeometryFacadePy::scale(PyObject* args)
{
PyObject* o;
double scale;
Base::Vector3d vec;
if (PyArg_ParseTuple(args, "O!d", &(Base::VectorPy::Type),&o, &scale)) {
if (PyArg_ParseTuple(args, "O!d", &(Base::VectorPy::Type), &o, &scale)) {
vec = static_cast<Base::VectorPy*>(o)->value();
getExternalGeometryFacadePtr()->scale(vec, scale);
Py_Return;
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O!d", &PyTuple_Type,&o, &scale)) {
if (PyArg_ParseTuple(args, "O!d", &PyTuple_Type, &o, &scale)) {
vec = Base::getVectorFromTuple<double>(o);
getExternalGeometryFacadePtr()->scale(vec, scale);
Py_Return;
@@ -234,28 +238,28 @@ PyObject* ExternalGeometryFacadePy::scale(PyObject *args)
return nullptr;
}
PyObject* ExternalGeometryFacadePy::transform(PyObject *args)
PyObject* ExternalGeometryFacadePy::transform(PyObject* args)
{
PyObject* o;
if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type),&o))
if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type), &o))
return nullptr;
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(o)->value();
getExternalGeometryFacadePtr()->transform(mat);
Py_Return;
}
PyObject* ExternalGeometryFacadePy::translate(PyObject *args)
PyObject* ExternalGeometryFacadePy::translate(PyObject* args)
{
PyObject* o;
Base::Vector3d vec;
if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&o)) {
if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &o)) {
vec = static_cast<Base::VectorPy*>(o)->value();
getExternalGeometryFacadePtr()->translate(vec);
Py_Return;
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O!", &PyTuple_Type,&o)) {
if (PyArg_ParseTuple(args, "O!", &PyTuple_Type, &o)) {
vec = Base::getVectorFromTuple<double>(o);
getExternalGeometryFacadePtr()->translate(vec);
Py_Return;
@@ -265,12 +269,12 @@ PyObject* ExternalGeometryFacadePy::translate(PyObject *args)
return nullptr;
}
PyObject* ExternalGeometryFacadePy::setExtension(PyObject *args)
PyObject* ExternalGeometryFacadePy::setExtension(PyObject* args)
{
PyObject* o;
if (PyArg_ParseTuple(args, "O!", &(Part::GeometryExtensionPy::Type),&o)) {
Part::GeometryExtension * ext;
ext = static_cast<Part::GeometryExtensionPy *>(o)->getGeometryExtensionPtr();
if (PyArg_ParseTuple(args, "O!", &(Part::GeometryExtensionPy::Type), &o)) {
Part::GeometryExtension* ext;
ext = static_cast<Part::GeometryExtensionPy*>(o)->getGeometryExtensionPtr();
// make copy of Python managed memory and wrap it in smart pointer
auto cpy = ext->copy();
@@ -283,154 +287,159 @@ PyObject* ExternalGeometryFacadePy::setExtension(PyObject *args)
return nullptr;
}
PyObject* ExternalGeometryFacadePy::getExtensionOfType(PyObject *args)
PyObject* ExternalGeometryFacadePy::getExtensionOfType(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
Base::Type type = Base::Type::fromName(o);
if(type != Base::Type::badType()) {
if (type != Base::Type::badType()) {
try {
std::shared_ptr<const Part::GeometryExtension> ext(this->getExternalGeometryFacadePtr()->getExtension(type));
std::shared_ptr<const Part::GeometryExtension> ext(
this->getExternalGeometryFacadePtr()->getExtension(type));
// we create a copy and transfer this copy's memory management responsibility to Python
// we create a copy and transfer this copy's memory management responsibility to
// Python
PyObject* cpy = ext->copyPyObject();
return cpy;
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
catch(const std::bad_weak_ptr&) {
PyErr_SetString(Part::PartExceptionOCCError, "Geometry extension does not exist anymore.");
catch (const std::bad_weak_ptr&) {
PyErr_SetString(Part::PartExceptionOCCError,
"Geometry extension does not exist anymore.");
return nullptr;
}
catch(Base::NotImplementedError&) {
PyErr_SetString(Part::PartExceptionOCCError, "Geometry extension does not implement a Python counterpart.");
catch (Base::NotImplementedError&) {
PyErr_SetString(Part::PartExceptionOCCError,
"Geometry extension does not implement a Python counterpart.");
return nullptr;
}
}
else
{
else {
PyErr_SetString(Part::PartExceptionOCCError, "Exception type does not exist");
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the name of the geometry extension type was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the name of the geometry extension type was expected");
return nullptr;
}
PyObject* ExternalGeometryFacadePy::getExtensionOfName(PyObject *args)
PyObject* ExternalGeometryFacadePy::getExtensionOfName(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
try {
std::shared_ptr<const Part::GeometryExtension> ext(this->getExternalGeometryFacadePtr()->getExtension(std::string(o)));
std::shared_ptr<const Part::GeometryExtension> ext(
this->getExternalGeometryFacadePtr()->getExtension(std::string(o)));
// we create a copy and transfer this copy's memory management responsibility to Python
PyObject* cpy = ext->copyPyObject();
return cpy;
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
catch(const std::bad_weak_ptr&) {
PyErr_SetString(Part::PartExceptionOCCError, "Geometry extension does not exist anymore.");
catch (const std::bad_weak_ptr&) {
PyErr_SetString(Part::PartExceptionOCCError,
"Geometry extension does not exist anymore.");
return nullptr;
}
catch(Base::NotImplementedError&) {
PyErr_SetString(Part::PartExceptionOCCError, "Geometry extension does not implement a Python counterpart.");
catch (Base::NotImplementedError&) {
PyErr_SetString(Part::PartExceptionOCCError,
"Geometry extension does not implement a Python counterpart.");
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the name of the geometry extension was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the name of the geometry extension was expected");
return nullptr;
}
PyObject* ExternalGeometryFacadePy::hasExtensionOfType(PyObject *args)
PyObject* ExternalGeometryFacadePy::hasExtensionOfType(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
Base::Type type = Base::Type::fromName(o);
if(type != Base::Type::badType()) {
if (type != Base::Type::badType()) {
try {
return Py::new_reference_to(Py::Boolean(this->getExternalGeometryFacadePtr()->hasExtension(type)));
return Py::new_reference_to(
Py::Boolean(this->getExternalGeometryFacadePtr()->hasExtension(type)));
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
else
{
else {
PyErr_SetString(Part::PartExceptionOCCError, "Exception type does not exist");
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the type of the geometry extension was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the type of the geometry extension was expected");
return nullptr;
}
PyObject* ExternalGeometryFacadePy::hasExtensionOfName(PyObject *args)
PyObject* ExternalGeometryFacadePy::hasExtensionOfName(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
try {
return Py::new_reference_to(Py::Boolean(this->getExternalGeometryFacadePtr()->hasExtension(std::string(o))));
return Py::new_reference_to(
Py::Boolean(this->getExternalGeometryFacadePtr()->hasExtension(std::string(o))));
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the type of the geometry extension was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the type of the geometry extension was expected");
return nullptr;
}
PyObject* ExternalGeometryFacadePy::deleteExtensionOfType(PyObject *args)
PyObject* ExternalGeometryFacadePy::deleteExtensionOfType(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
Base::Type type = Base::Type::fromName(o);
if(type != Base::Type::badType()) {
if (type != Base::Type::badType()) {
try {
this->getExternalGeometryFacadePtr()->deleteExtension(type);
Py_Return;
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
else
{
else {
PyErr_SetString(Part::PartExceptionOCCError, "Type does not exist");
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with a type object was expected");
return nullptr;
}
PyObject* ExternalGeometryFacadePy::deleteExtensionOfName(PyObject *args)
PyObject* ExternalGeometryFacadePy::deleteExtensionOfName(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
@@ -439,38 +448,40 @@ PyObject* ExternalGeometryFacadePy::deleteExtensionOfName(PyObject *args)
this->getExternalGeometryFacadePtr()->deleteExtension(std::string(o));
Py_Return;
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the name of the extension was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the name of the extension was expected");
return nullptr;
}
PyObject* ExternalGeometryFacadePy::getExtensions(PyObject *args)
PyObject* ExternalGeometryFacadePy::getExtensions(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")){
if (!PyArg_ParseTuple(args, "")) {
PyErr_SetString(Part::PartExceptionOCCError, "No arguments were expected");
return nullptr;
}
try {
const std::vector<std::weak_ptr<const Part::GeometryExtension>> ext = this->getExternalGeometryFacadePtr()->getExtensions();
const std::vector<std::weak_ptr<const Part::GeometryExtension>> ext =
this->getExternalGeometryFacadePtr()->getExtensions();
Py::List list;
for (std::size_t i=0; i<ext.size(); ++i) {
for (std::size_t i = 0; i < ext.size(); ++i) {
std::shared_ptr<const Part::GeometryExtension> p = ext[i].lock();
if(p) {
if (p) {
// we create a python copy and add it to the list
try {
list.append(Py::asObject(p->copyPyObject()));
}
catch(Base::NotImplementedError&) {
catch (Base::NotImplementedError&) {
// silently ignoring extensions not having a Python object
}
}
@@ -478,11 +489,10 @@ PyObject* ExternalGeometryFacadePy::getExtensions(PyObject *args)
return Py::new_reference_to(list);
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
Py::Boolean ExternalGeometryFacadePy::getConstruction() const
@@ -490,7 +500,7 @@ Py::Boolean ExternalGeometryFacadePy::getConstruction() const
return Py::Boolean(getExternalGeometryFacadePtr()->getConstruction());
}
void ExternalGeometryFacadePy::setConstruction(Py::Boolean arg)
void ExternalGeometryFacadePy::setConstruction(Py::Boolean arg)
{
if (getExternalGeometryFacadePtr()->getTypeId() != Part::GeomPoint::getClassTypeId())
getExternalGeometryFacadePtr()->setConstruction(arg);
@@ -519,17 +529,17 @@ Py::Object ExternalGeometryFacadePy::getGeometry() const
return Py::Object(geo->getPyObject(), true);
}
void ExternalGeometryFacadePy::setGeometry(Py::Object arg)
void ExternalGeometryFacadePy::setGeometry(Py::Object arg)
{
if (PyObject_TypeCheck(arg.ptr(), &(Part::GeometryPy::Type))) {
Part::GeometryPy * gp = static_cast<Part::GeometryPy *>(arg.ptr());
Part::GeometryPy* gp = static_cast<Part::GeometryPy*>(arg.ptr());
getExternalGeometryFacadePtr()->setGeometry(gp->getGeometryPtr()->clone());
}
}
PyObject *ExternalGeometryFacadePy::getCustomAttributes(const char* /*attr*/) const
PyObject* ExternalGeometryFacadePy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}

View File

@@ -23,8 +23,8 @@
#ifndef SKETCHER_GeoEnum_H
#define SKETCHER_GeoEnum_H
#include <functional>
#include <Mod/Sketcher/SketcherGlobal.h>
#include <functional>
namespace Sketcher
{
@@ -56,46 +56,49 @@ namespace Sketcher
*
* Geometry shapes having more or different elements than those supported by the PointPos
* struct, such as conics, in particular an arc of ellipse, are called complex geometries. The extra
* elements of complex geometries are actual separate geometries (focus of an ellipse, line defining the
* major axis of an ellipse, circle representing the weight of a BSpline), and they are call InternalAlignment
* geometries.
* elements of complex geometries are actual separate geometries (focus of an ellipse, line defining
* the major axis of an ellipse, circle representing the weight of a BSpline), and they are call
* InternalAlignment geometries.
*
* For Geometry lists, refer to GeoListModel template.
*/
enum GeoEnum
{
RtPnt = -1, // GeoId of the Root Point
HAxis = -1, // GeoId of the Horizontal Axis
VAxis = -2, // GeoId of the Vertical Axis
RefExt = -3, // Starting GeoID of external geometry ( negative geoIds starting at this index)
GeoUndef = -2000, // GeoId of an undefined Geometry (uninitialised or unused GeoId)
RtPnt = -1, // GeoId of the Root Point
HAxis = -1, // GeoId of the Horizontal Axis
VAxis = -2, // GeoId of the Vertical Axis
RefExt = -3,// Starting GeoID of external geometry ( negative geoIds starting at this index)
GeoUndef = -2000,// GeoId of an undefined Geometry (uninitialised or unused GeoId)
};
/*!
* @brief PointPos lets us refer to different aspects of a piece of geometry.
* @details sketcher::none refers to an edge itself (eg., for a Perpendicular constraint
* on two lines). sketcher::start and sketcher::end denote the endpoints of lines or bounded curves.
* Sketcher::mid denotes geometries with geometrical centers (eg., circle, ellipse). Bare points use 'start'.
* More complex geometries like parabola focus or b-spline knots use InternalAlignment constraints
* in addition to PointPos.
* Sketcher::mid denotes geometries with geometrical centers (eg., circle, ellipse). Bare points use
* 'start'. More complex geometries like parabola focus or b-spline knots use InternalAlignment
* constraints in addition to PointPos.
*/
enum class PointPos : int {
none = 0, // Edge of a geometry
start = 1, // Starting point of a geometry
end = 2, // End point of a geometry
mid = 3 // Mid point of a geometry
enum class PointPos : int
{
none = 0, // Edge of a geometry
start = 1,// Starting point of a geometry
end = 2, // End point of a geometry
mid = 3 // Mid point of a geometry
};
/** @brief Struct for storing a {GeoId, PointPos} pair.
*
* @details
* {GeoId, PointPos} is pervasive in the sketcher as means to identify geometry (edges) and geometry elements (vertices).
* {GeoId, PointPos} is pervasive in the sketcher as means to identify geometry (edges) and geometry
* elements (vertices).
*
* GeoElementId intends to substitute this pair whenever appropriate. For example in containers and ordered containers.
*
* It has overloaded equality operator and specialised std::less so that it can safely be used in containers, including
* GeoElementId intends to substitute this pair whenever appropriate. For example in containers and
* ordered containers.
*
* It has overloaded equality operator and specialised std::less so that it can safely be used in
* containers, including ordered containers.
*
*/
class SketcherExport GeoElementId
{
@@ -109,7 +112,7 @@ public:
bool operator==(const GeoElementId& obj) const;
/** @brief inequality operator
*/
*/
bool operator!=(const GeoElementId& obj) const;
/** @brief Underlying GeoId (see GeoEnum for definition)
@@ -135,15 +138,18 @@ public:
};
// inline constexpr constructor
inline constexpr GeoElementId::GeoElementId(int geoId, PointPos pos): GeoId(geoId), Pos(pos)
{
}
inline constexpr GeoElementId::GeoElementId(int geoId, PointPos pos)
: GeoId(geoId),
Pos(pos)
{}
inline bool GeoElementId::isCurve() const {
inline bool GeoElementId::isCurve() const
{
return Pos == PointPos::none;
}
inline int GeoElementId::posIdAsInt() const {
inline int GeoElementId::posIdAsInt() const
{
return static_cast<int>(Pos);
}
@@ -153,18 +159,19 @@ constexpr const GeoElementId GeoElementId::HAxis = GeoElementId(GeoEnum::HAxis,
constexpr const GeoElementId GeoElementId::VAxis = GeoElementId(GeoEnum::VAxis, PointPos::none);
#endif
} // namespace Sketcher
}// namespace Sketcher
namespace std
{
template<> struct less<Sketcher::GeoElementId>
template<>
struct less<Sketcher::GeoElementId>
{
bool operator()(const Sketcher::GeoElementId& lhs, const Sketcher::GeoElementId& rhs) const
{
bool operator() (const Sketcher::GeoElementId& lhs, const Sketcher::GeoElementId& rhs) const
{
return (lhs.GeoId != rhs.GeoId)?(lhs.GeoId < rhs.GeoId):(static_cast<int>(lhs.Pos) < static_cast<int>(rhs.Pos));
}
};
} // namespace std
#endif // SKETCHER_GeoEnum_H
return (lhs.GeoId != rhs.GeoId) ? (lhs.GeoId < rhs.GeoId)
: (static_cast<int>(lhs.Pos) < static_cast<int>(rhs.Pos));
}
};
}// namespace std
#endif// SKETCHER_GeoEnum_H

View File

@@ -22,8 +22,8 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cassert>
#endif // #ifndef _PreComp_
#include <cassert>
#endif// #ifndef _PreComp_
#include <boost/core/ignore_unused.hpp>
@@ -37,179 +37,188 @@
using namespace Sketcher;
// Vector is moved
template <typename T>
GeoListModel<T>::GeoListModel( std::vector<T> && geometrylist,
int intgeocount,
bool ownerT): geomlist(std::move(geometrylist)),
intGeoCount(intgeocount),
OwnerT(ownerT),
indexInit(false)
{
}
template<typename T>
GeoListModel<T>::GeoListModel(std::vector<T>&& geometrylist, int intgeocount, bool ownerT)
: geomlist(std::move(geometrylist)),
intGeoCount(intgeocount),
OwnerT(ownerT),
indexInit(false)
{}
// Vector is shallow copied (copy constructed)
template <typename T>
GeoListModel<T>::GeoListModel( const std::vector<T> & geometrylist,
int intgeocount): geomlist(geometrylist), // copy constructed here
intGeoCount(intgeocount),
OwnerT(false),
indexInit(false)
{
template<typename T>
GeoListModel<T>::GeoListModel(const std::vector<T>& geometrylist,
int intgeocount)
: geomlist(geometrylist),// copy constructed here
intGeoCount(intgeocount),
OwnerT(false),
indexInit(false)
{}
}
template <typename T>
template<typename T>
GeoListModel<T>::~GeoListModel()
{
if(OwnerT) {
for(auto & g : geomlist)
if (OwnerT) {
for (auto& g : geomlist)
delete g;
}
}
template <typename T>
GeoListModel<T> GeoListModel<T>::getGeoListModel(std::vector<T> && geometrylist, int intgeocount, bool ownerT)
template<typename T>
GeoListModel<T> GeoListModel<T>::getGeoListModel(std::vector<T>&& geometrylist, int intgeocount,
bool ownerT)
{
return GeoListModel(std::move(geometrylist), intgeocount, ownerT);
}
template <typename T>
const GeoListModel<T> GeoListModel<T>::getGeoListModel(const std::vector<T> &geometrylist, int intgeocount)
template<typename T>
const GeoListModel<T> GeoListModel<T>::getGeoListModel(const std::vector<T>& geometrylist,
int intgeocount)
{
return GeoListModel(geometrylist, intgeocount);
}
template <typename T>
template<typename T>
int GeoListModel<T>::getGeoIdFromGeomListIndex(int index) const
{
assert(index < int(geomlist.size()));
if(index < intGeoCount)
if (index < intGeoCount)
return index;
else
return ( index - geomlist.size());
return (index - geomlist.size());
}
template <typename T>
const Part::Geometry * GeoListModel<T>::getGeometryFromGeoId(const std::vector<T> & geometrylist, int geoId)
template<typename T>
const Part::Geometry* GeoListModel<T>::getGeometryFromGeoId(const std::vector<T>& geometrylist,
int geoId)
{
if constexpr (std::is_same<T,GeometryPtr>()) {
if constexpr (std::is_same<T, GeometryPtr>()) {
if (geoId >= 0)
return geometrylist[geoId];
else
return geometrylist[geometrylist.size()+geoId];
return geometrylist[geometrylist.size() + geoId];
}
else if constexpr (std::is_same<T,GeometryFacadeUniquePtr>()) {
else if constexpr (std::is_same<T, GeometryFacadeUniquePtr>()) {
if (geoId >= 0)
return geometrylist[geoId]->getGeometry();
else
return geometrylist[geometrylist.size()+geoId]->getGeometry();
return geometrylist[geometrylist.size() + geoId]->getGeometry();
}
}
template <typename T>
const Sketcher::GeometryFacade * GeoListModel<T>::getGeometryFacadeFromGeoId(const std::vector<T> & geometrylist, int geoId)
template<typename T>
const Sketcher::GeometryFacade*
GeoListModel<T>::getGeometryFacadeFromGeoId(const std::vector<T>& geometrylist, int geoId)
{
if constexpr (std::is_same<T,GeometryPtr>()) {
if constexpr (std::is_same<T, GeometryPtr>()) {
if (geoId >= 0)
return GeometryFacade::getFacade(geometrylist[geoId]).release();
else
return GeometryFacade::getFacade(geometrylist[geometrylist.size()+geoId]).release();
return GeometryFacade::getFacade(geometrylist[geometrylist.size() + geoId]).release();
}
else if constexpr (std::is_same<T,GeometryFacadeUniquePtr>()) {
else if constexpr (std::is_same<T, GeometryFacadeUniquePtr>()) {
if (geoId >= 0)
return geometrylist[geoId].get();
else
return geometrylist[geometrylist.size()+geoId].get();
return geometrylist[geometrylist.size() + geoId].get();
}
}
// this function is used to simulate cyclic periodic negative geometry indices (for external geometry)
template <typename T>
const Part::Geometry * GeoListModel<T>::getGeometryFromGeoId(int geoId) const
// this function is used to simulate cyclic periodic negative geometry indices (for external
// geometry)
template<typename T>
const Part::Geometry* GeoListModel<T>::getGeometryFromGeoId(int geoId) const
{
return GeoListModel<T>::getGeometryFromGeoId(geomlist, geoId);
}
template <typename T>
const Sketcher::GeometryFacade * GeoListModel<T>::getGeometryFacadeFromGeoId(int geoId) const
template<typename T>
const Sketcher::GeometryFacade* GeoListModel<T>::getGeometryFacadeFromGeoId(int geoId) const
{
return GeoListModel<T>::getGeometryFacadeFromGeoId(geomlist, geoId);
}
template <typename T>
template<typename T>
Base::Vector3d GeoListModel<T>::getPoint(int geoId, Sketcher::PointPos pos) const
{
const Part::Geometry * geo = getGeometryFromGeoId(geoId);
const Part::Geometry* geo = getGeometryFromGeoId(geoId);
return getPoint(geo, pos);
}
template <typename T>
Base::Vector3d GeoListModel<T>::getPoint(const GeoElementId & geid) const
template<typename T>
Base::Vector3d GeoListModel<T>::getPoint(const GeoElementId& geid) const
{
return getPoint(geid.GeoId, geid.Pos);
}
template <typename T>
Base::Vector3d GeoListModel<T>::getPoint(const Part::Geometry * geo, Sketcher::PointPos pos) const
template<typename T>
Base::Vector3d GeoListModel<T>::getPoint(const Part::Geometry* geo, Sketcher::PointPos pos) const
{
using namespace Sketcher;
if (geo->getTypeId() == Part::GeomPoint::getClassTypeId()) {
const Part::GeomPoint *p = static_cast<const Part::GeomPoint*>(geo);
const Part::GeomPoint* p = static_cast<const Part::GeomPoint*>(geo);
if (pos == PointPos::start || pos == PointPos::mid || pos == PointPos::end)
return p->getPoint();
} else if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = static_cast<const Part::GeomLineSegment*>(geo);
}
else if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment* lineSeg = static_cast<const Part::GeomLineSegment*>(geo);
if (pos == PointPos::start)
return lineSeg->getStartPoint();
else if (pos == PointPos::end)
return lineSeg->getEndPoint();
} else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle = static_cast<const Part::GeomCircle*>(geo);
}
else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle* circle = static_cast<const Part::GeomCircle*>(geo);
if (pos == PointPos::mid)
return circle->getCenter();
} else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
const Part::GeomEllipse *ellipse = static_cast<const Part::GeomEllipse*>(geo);
}
else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
const Part::GeomEllipse* ellipse = static_cast<const Part::GeomEllipse*>(geo);
if (pos == PointPos::mid)
return ellipse->getCenter();
} else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *aoc = static_cast<const Part::GeomArcOfCircle*>(geo);
}
else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle* aoc = static_cast<const Part::GeomArcOfCircle*>(geo);
if (pos == PointPos::start)
return aoc->getStartPoint(/*emulateCCW=*/true);
else if (pos == PointPos::end)
return aoc->getEndPoint(/*emulateCCW=*/true);
else if (pos == PointPos::mid)
return aoc->getCenter();
} else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
const Part::GeomArcOfEllipse *aoc = static_cast<const Part::GeomArcOfEllipse*>(geo);
}
else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
const Part::GeomArcOfEllipse* aoc = static_cast<const Part::GeomArcOfEllipse*>(geo);
if (pos == PointPos::start)
return aoc->getStartPoint(/*emulateCCW=*/true);
else if (pos == PointPos::end)
return aoc->getEndPoint(/*emulateCCW=*/true);
else if (pos == PointPos::mid)
return aoc->getCenter();
} else if (geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
const Part::GeomArcOfHyperbola *aoh = static_cast<const Part::GeomArcOfHyperbola*>(geo);
}
else if (geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
const Part::GeomArcOfHyperbola* aoh = static_cast<const Part::GeomArcOfHyperbola*>(geo);
if (pos == PointPos::start)
return aoh->getStartPoint();
else if (pos == PointPos::end)
return aoh->getEndPoint();
else if (pos == PointPos::mid)
return aoh->getCenter();
} else if (geo->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) {
const Part::GeomArcOfParabola *aop = static_cast<const Part::GeomArcOfParabola*>(geo);
}
else if (geo->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) {
const Part::GeomArcOfParabola* aop = static_cast<const Part::GeomArcOfParabola*>(geo);
if (pos == PointPos::start)
return aop->getStartPoint();
else if (pos == PointPos::end)
return aop->getEndPoint();
else if (pos == PointPos::mid)
return aop->getCenter();
} else if (geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) {
const Part::GeomBSplineCurve *bsp = static_cast<const Part::GeomBSplineCurve*>(geo);
}
else if (geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) {
const Part::GeomBSplineCurve* bsp = static_cast<const Part::GeomBSplineCurve*>(geo);
if (pos == PointPos::start)
return bsp->getStartPoint();
else if (pos == PointPos::end)
@@ -219,20 +228,20 @@ Base::Vector3d GeoListModel<T>::getPoint(const Part::Geometry * geo, Sketcher::P
return Base::Vector3d();
}
template <typename T>
template<typename T>
void GeoListModel<T>::rebuildVertexIndex() const
{
VertexId2GeoElementId.clear();
GeoElementId2VertexId.clear();
int geoId=0;
int pointId=0;
int geoId = 0;
int pointId = 0;
auto addGeoElement = [this, &pointId](int geoId, PointPos pos) {
VertexId2GeoElementId.emplace_back(geoId,pos);
VertexId2GeoElementId.emplace_back(geoId, pos);
GeoElementId2VertexId.emplace(std::piecewise_construct,
std::forward_as_tuple(geoId, pos),
std::forward_as_tuple(pointId++));
std::forward_as_tuple(geoId, pos),
std::forward_as_tuple(pointId++));
};
if (geomlist.size() <= 2)
@@ -241,72 +250,75 @@ void GeoListModel<T>::rebuildVertexIndex() const
Base::Type type;
if constexpr (std::is_same<T, Part::Geometry *>::value)
if constexpr (std::is_same<T, Part::Geometry*>::value)
type = (*it)->getTypeId();
else if constexpr (std::is_same<T, std::unique_ptr<const Sketcher::GeometryFacade>>::value)
type = (*it)->getGeometry()->getTypeId();
if ( geoId > getInternalCount())
if (geoId > getInternalCount())
geoId = -getExternalCount();
if (type == Part::GeomPoint::getClassTypeId()) {
addGeoElement(geoId,PointPos::start);
} else if (type == Part::GeomLineSegment::getClassTypeId() ||
type == Part::GeomBSplineCurve::getClassTypeId()) {
addGeoElement(geoId,PointPos::start);
addGeoElement(geoId,PointPos::end);
} else if (type == Part::GeomCircle::getClassTypeId() ||
type == Part::GeomEllipse::getClassTypeId()) {
addGeoElement(geoId,PointPos::mid);
} else if (type == Part::GeomArcOfCircle::getClassTypeId() ||
type == Part::GeomArcOfEllipse::getClassTypeId() ||
type == Part::GeomArcOfHyperbola::getClassTypeId() ||
type == Part::GeomArcOfParabola::getClassTypeId()) {
addGeoElement(geoId,PointPos::start);
addGeoElement(geoId,PointPos::end);
addGeoElement(geoId,PointPos::mid);
addGeoElement(geoId, PointPos::start);
}
else if (type == Part::GeomLineSegment::getClassTypeId()
|| type == Part::GeomBSplineCurve::getClassTypeId()) {
addGeoElement(geoId, PointPos::start);
addGeoElement(geoId, PointPos::end);
}
else if (type == Part::GeomCircle::getClassTypeId()
|| type == Part::GeomEllipse::getClassTypeId()) {
addGeoElement(geoId, PointPos::mid);
}
else if (type == Part::GeomArcOfCircle::getClassTypeId()
|| type == Part::GeomArcOfEllipse::getClassTypeId()
|| type == Part::GeomArcOfHyperbola::getClassTypeId()
|| type == Part::GeomArcOfParabola::getClassTypeId()) {
addGeoElement(geoId, PointPos::start);
addGeoElement(geoId, PointPos::end);
addGeoElement(geoId, PointPos::mid);
}
}
indexInit = true;
}
template <typename T>
template<typename T>
Sketcher::GeoElementId GeoListModel<T>::getGeoElementIdFromVertexId(int vertexId)
{
if(!indexInit) // lazy initialised
if (!indexInit)// lazy initialised
rebuildVertexIndex();
return VertexId2GeoElementId[vertexId];
}
template <typename T>
int GeoListModel<T>::getVertexIdFromGeoElementId(const Sketcher::GeoElementId & geoelementId) const
template<typename T>
int GeoListModel<T>::getVertexIdFromGeoElementId(const Sketcher::GeoElementId& geoelementId) const
{
if(!indexInit) // lazy initialised
if (!indexInit)// lazy initialised
rebuildVertexIndex();
auto found = std::find(VertexId2GeoElementId.begin(), VertexId2GeoElementId.end(), geoelementId);
auto found =
std::find(VertexId2GeoElementId.begin(), VertexId2GeoElementId.end(), geoelementId);
if( found != VertexId2GeoElementId.end() )
if (found != VertexId2GeoElementId.end())
return std::distance(found, VertexId2GeoElementId.begin());
THROWM(Base::IndexError, "GeoElementId not indexed");
}
namespace Sketcher {
namespace Sketcher
{
// Template specialisations
template <>
template<>
GeoListModel<GeometryFacadeUniquePtr>::GeoListModel(
std::vector<GeometryFacadeUniquePtr> && geometrylist,
int intgeocount,
bool ownerT) : geomlist(std::move(geometrylist)),
intGeoCount(intgeocount),
OwnerT(false),
indexInit(false)
std::vector<GeometryFacadeUniquePtr>&& geometrylist, int intgeocount, bool ownerT)
: geomlist(std::move(geometrylist)),
intGeoCount(intgeocount),
OwnerT(false),
indexInit(false)
{
// GeometryFacades hold the responsibility for releasing the resources.
//
@@ -321,62 +333,72 @@ GeoListModel<GeometryFacadeUniquePtr>::GeoListModel(
boost::ignore_unused(ownerT);
}
template <>
template<>
GeoListModel<GeometryFacadeUniquePtr>::GeoListModel(
const std::vector<GeometryFacadeUniquePtr> & geometrylist,
int intgeocount): intGeoCount(intgeocount),
OwnerT(false),
indexInit(false)
const std::vector<GeometryFacadeUniquePtr>& geometrylist, int intgeocount)
: intGeoCount(intgeocount),
OwnerT(false),
indexInit(false)
{
// GeometryFacades are movable, but not copiable, so they need to be reconstructed (shallow copy of vector)
// Under the Single Responsibility Principle, these will not take over a responsibility that shall be enforced
// on the original GeometryFacade. Use the move version of getGeoListModel if moving the responsibility is intended.
// GeometryFacades are movable, but not copiable, so they need to be reconstructed (shallow copy
// of vector) Under the Single Responsibility Principle, these will not take over a
// responsibility that shall be enforced on the original GeometryFacade. Use the move version of
// getGeoListModel if moving the responsibility is intended.
geomlist.reserve(geometrylist.size());
for(auto & v : geometrylist) {
for (auto& v : geometrylist) {
geomlist.push_back(GeometryFacade::getFacade(v->getGeometry()));
}
}
template <> SketcherExport
GeoListModel<std::unique_ptr<const Sketcher::GeometryFacade>>::~GeoListModel()
template<>
SketcherExport GeoListModel<std::unique_ptr<const Sketcher::GeometryFacade>>::~GeoListModel()
{
// GeometryFacade is responsible for taken ownership of its pointers and deleting them.
}
// instantiate the types so that other translation units can access template constructors
template class SketcherExport GeoListModel<Part::Geometry *>;
template class SketcherExport GeoListModel<Part::Geometry*>;
#if !defined(__MINGW32__)
template class SketcherExport GeoListModel<std::unique_ptr<const Sketcher::GeometryFacade>>;
#else
// Remark: It looks like when implementing a method of GeoListModel for GeometryFacadeUniquePtr then under MinGW
// the explicit template instantiation doesn't do anything. As workaround all other methods must be declared separately
template SketcherExport const Part::Geometry* GeoListModel<GeometryFacadeUniquePtr>::getGeometryFromGeoId(int geoId) const;
template SketcherExport const Sketcher::GeometryFacade* GeoListModel<GeometryFacadeUniquePtr>::getGeometryFacadeFromGeoId(int geoId) const;
template SketcherExport int GeoListModel<GeometryFacadeUniquePtr>::getGeoIdFromGeomListIndex(int index) const;
template SketcherExport int GeoListModel<GeometryFacadeUniquePtr>::getVertexIdFromGeoElementId(const Sketcher::GeoElementId &) const;
template SketcherExport GeoElementId GeoListModel<GeometryFacadeUniquePtr>::getGeoElementIdFromVertexId(int);
template SketcherExport Base::Vector3d GeoListModel<GeometryFacadeUniquePtr>::getPoint(int geoId, Sketcher::PointPos pos) const;
template SketcherExport Base::Vector3d GeoListModel<GeometryFacadeUniquePtr>::getPoint(const GeoElementId &) const;
template SketcherExport GeoListModel<GeometryFacadeUniquePtr> GeoListModel<GeometryFacadeUniquePtr>::getGeoListModel
(std::vector<GeometryFacadeUniquePtr>&& geometrylist, int intgeocount, bool ownerT);
// Remark: It looks like when implementing a method of GeoListModel for GeometryFacadeUniquePtr then
// under MinGW the explicit template instantiation doesn't do anything. As workaround all other
// methods must be declared separately
template SketcherExport const Part::Geometry*
GeoListModel<GeometryFacadeUniquePtr>::getGeometryFromGeoId(int geoId) const;
template SketcherExport const Sketcher::GeometryFacade*
GeoListModel<GeometryFacadeUniquePtr>::getGeometryFacadeFromGeoId(int geoId) const;
template SketcherExport int
GeoListModel<GeometryFacadeUniquePtr>::getGeoIdFromGeomListIndex(int index) const;
template SketcherExport int GeoListModel<GeometryFacadeUniquePtr>::getVertexIdFromGeoElementId(
const Sketcher::GeoElementId&) const;
template SketcherExport GeoElementId
GeoListModel<GeometryFacadeUniquePtr>::getGeoElementIdFromVertexId(int);
template SketcherExport Base::Vector3d
GeoListModel<GeometryFacadeUniquePtr>::getPoint(int geoId, Sketcher::PointPos pos) const;
template SketcherExport Base::Vector3d
GeoListModel<GeometryFacadeUniquePtr>::getPoint(const GeoElementId&) const;
template SketcherExport GeoListModel<GeometryFacadeUniquePtr>
GeoListModel<GeometryFacadeUniquePtr>::getGeoListModel(
std::vector<GeometryFacadeUniquePtr>&& geometrylist, int intgeocount, bool ownerT);
#endif
} // namespace Sketcher
}// namespace Sketcher
GeoListFacade Sketcher::getGeoListFacade(const GeoList & geolist)
GeoListFacade Sketcher::getGeoListFacade(const GeoList& geolist)
{
std::vector<std::unique_ptr<const GeometryFacade>> facade;
facade.reserve( geolist.geomlist.size());
facade.reserve(geolist.geomlist.size());
for(auto geo : geolist.geomlist)
for (auto geo : geolist.geomlist)
facade.push_back(GeometryFacade::getFacade(geo));
auto geolistfacade = GeoListFacade::getGeoListModel(std::move(facade), geolist.getInternalCount());
auto geolistfacade =
GeoListFacade::getGeoListModel(std::move(facade), geolist.getInternalCount());
return geolistfacade;
}

View File

@@ -30,19 +30,23 @@
#include "GeometryFacade.h"
namespace Base {
template< typename T >
class Vector3;
namespace Base
{
template<typename T>
class Vector3;
}
namespace Part {
class Geometry;
namespace Part
{
class Geometry;
}
namespace Sketcher {
namespace Sketcher
{
}
namespace Sketcher {
namespace Sketcher
{
/** @brief Class for managing internal and external geometry as a single object
* @details
@@ -66,107 +70,126 @@ namespace Sketcher {
* N.B.: Note that the index of the geomlist (all layers) and the GeoId can be converted
* from each other as needed using the member functions (and sometimes the static functions).
*/
template <typename T>
class GeoListModel {
template<typename T>
class GeoListModel
{
using Vector3d = Base::Vector3<double>;
protected:
/** @brief
* Constructors are protected, use static methods getGeoListModel() to construct the objects instead.
* Constructors are protected, use static methods getGeoListModel() to construct the objects
* instead.
*
* Constructs the object from a list of geometry in geomlist format and the number of internal
* geometries (non external) present in the list.
*
* @param geometrylist: the geometry in geomlist format (external after internal in a single vector).
* @param geometrylist: the geometry in geomlist format (external after internal in a single
* vector).
* @param intgeocount: the number of internal geometries (non external) in the list.
* @param ownerT: indicates whether the GeoListModel takes ownership of the elements of the std::vector<T> (for pointers)
* @param ownerT: indicates whether the GeoListModel takes ownership of the elements of the
* std::vector<T> (for pointers)
*/
explicit GeoListModel(std::vector<T> && geometrylist, int intgeocount, bool ownerT = false);
explicit GeoListModel(std::vector<T>&& geometrylist, int intgeocount, bool ownerT = false);
explicit GeoListModel(const std::vector<T> & geometrylist, int intgeocount);
explicit GeoListModel(const std::vector<T>& geometrylist, int intgeocount);
public:
/** @brief Destructor having type dependent behaviour
*
* @warning
* For GeoList, the destructor will destruct the Part::Geometry pointers * only * if it was constructed with ownerT = true.
* For GeoList, the destructor will destruct the Part::Geometry pointers * only * if it was
* constructed with ownerT = true.
*
* For GeoListFacade, the smart pointers will be deleted. However, a GeometryFacade does * not * delete the underlying naked pointers
* by default (which is mostly the desired behaviour as the ownership of the pointers belongs to sketchObject). If GeometryFacade is
* to delete the underlying naked pointers (because it is a temporal deep copy), then the GeometryFacade needs to get ownership (see
* setOwner method).
* For GeoListFacade, the smart pointers will be deleted. However, a GeometryFacade does * not *
* delete the underlying naked pointers by default (which is mostly the desired behaviour as the
* ownership of the pointers belongs to sketchObject). If GeometryFacade is to delete the
* underlying naked pointers (because it is a temporal deep copy), then the GeometryFacade needs
* to get ownership (see setOwner method).
*
*/
~GeoListModel();
// Explicit deletion to show intent (not that it is needed). This is a move only type.
GeoListModel(const GeoListModel &) = delete;
GeoListModel(const GeoListModel&) = delete;
GeoListModel& operator=(const GeoListModel&) = delete;
// enable move constructor and move assignment. This is a move only type.
GeoListModel(GeoListModel &&) = default;
GeoListModel(GeoListModel&&) = default;
GeoListModel& operator=(GeoListModel&&) = default;
/** @brief
* GeoListModel manages the lifetime of its internal std::vector. This means that while the actual ownership
* of the T parameter needs to be specified or separately handled. In the absence of that, a new vector will
* be created and the T elements shallow copied to the internal vector.
* GeoListModel manages the lifetime of its internal std::vector. This means that while the
* actual ownership of the T parameter needs to be specified or separately handled. In the
* absence of that, a new vector will be created and the T elements shallow copied to the
* internal vector.
*
* The constness of the GeoListModel is tied to the constness of the std::vector from which it is constructed.
* The constness of the GeoListModel is tied to the constness of the std::vector from which it
* is constructed.
*
* @warning
* For GeoListFacade ownership at GeoListModel level cannot be taken (ownerT cannot be true). An assertion is raised
* if this happens. The ownership needs to be specified on the GeoListFacade objects themselves (setOwner method).
* For GeoListFacade ownership at GeoListModel level cannot be taken (ownerT cannot be true). An
* assertion is raised if this happens. The ownership needs to be specified on the GeoListFacade
* objects themselves (setOwner method).
*/
static GeoListModel<T> getGeoListModel(std::vector<T> && geometrylist, int intgeocount, bool ownerT = false);
static const GeoListModel<T> getGeoListModel(const std::vector<T> & geometrylist, int intgeocount);
static GeoListModel<T> getGeoListModel(std::vector<T>&& geometrylist, int intgeocount,
bool ownerT = false);
static const GeoListModel<T> getGeoListModel(const std::vector<T>& geometrylist,
int intgeocount);
/** @brief
* returns the geometry given by the GeoId
*/
const Part::Geometry * getGeometryFromGeoId(int geoId) const;
* returns the geometry given by the GeoId
*/
const Part::Geometry* getGeometryFromGeoId(int geoId) const;
/** @brief returns a geometryfacade
* @warning If the underlying model of the list is a naked pointed (Part::Geometry *), i.e. a GeoList instantiation, the
* client (the user) bears responsibility for releasing the GeometryFacade pointer!!
* @warning If the underlying model of the list is a naked pointed (Part::Geometry *), i.e. a
* GeoList instantiation, the client (the user) bears responsibility for releasing the
* GeometryFacade pointer!!
*
* This is not a problem when the model of the list is a std::unique_ptr<Sketcher::GeometryFacade>, because the lifetime is tied to
* the GeometryFacade. It will destruct the pointer if it is the owner.
* This is not a problem when the model of the list is a
* std::unique_ptr<Sketcher::GeometryFacade>, because the lifetime is tied to the
* GeometryFacade. It will destruct the pointer if it is the owner.
*/
const Sketcher::GeometryFacade * getGeometryFacadeFromGeoId(int geoId) const;
const Sketcher::GeometryFacade* getGeometryFacadeFromGeoId(int geoId) const;
/** @brief
* returns the GeoId index from the index in the geometry in geomlist format with which it was constructed.
*
* @param index: the index of the list of geometry in geomlist format.
*/
* returns the GeoId index from the index in the geometry in geomlist format with which it was
* constructed.
*
* @param index: the index of the list of geometry in geomlist format.
*/
int getGeoIdFromGeomListIndex(int index) const;
/** @brief
* returns the geometry given by the GeoId in the geometrylist in geomlist format provided as a parameter.
*
* @param geometrylist: the geometry in geomlist format (external after internal in a single vector).
*
* @param index: the index of the list of geometry in geomlist format.
*/
static const Part::Geometry * getGeometryFromGeoId(const std::vector<T> & geometrylist, int geoId);
* returns the geometry given by the GeoId in the geometrylist in geomlist format provided as a
* parameter.
*
* @param geometrylist: the geometry in geomlist format (external after internal in a single
* vector).
*
* @param index: the index of the list of geometry in geomlist format.
*/
static const Part::Geometry* getGeometryFromGeoId(const std::vector<T>& geometrylist,
int geoId);
/** @brief returns a geometry facade
* @warning If the underlying model of the list is a naked pointed (Part::Geometry *), the client (the user) bears responsibility
* for releasing the GeometryFacade pointer!!
* @warning If the underlying model of the list is a naked pointed (Part::Geometry *), the
* client (the user) bears responsibility for releasing the GeometryFacade pointer!!
*
* This is not a problem when the model of the list is a std::unique_ptr<Sketcher::GeometryFacade>, because the lifetime is tied to
* the model itself.
* This is not a problem when the model of the list is a
* std::unique_ptr<Sketcher::GeometryFacade>, because the lifetime is tied to the model itself.
*/
static const Sketcher::GeometryFacade * getGeometryFacadeFromGeoId(const std::vector<T> & geometrylist, int geoId);
static const Sketcher::GeometryFacade*
getGeometryFacadeFromGeoId(const std::vector<T>& geometrylist, int geoId);
/** @brief
* Obtain a GeoElementId class {GeoId, Pos} given a VertexId.
*
* A vertexId is a positive index of the vertex, where indices of external geometry taken higher positive values than normal geometry.
* It is the same format of vertex numbering used in the Sketcher, Sketch.cpp, and ViewProviderSketch.
* A vertexId is a positive index of the vertex, where indices of external geometry taken higher
* positive values than normal geometry. It is the same format of vertex numbering used in the
* Sketcher, Sketch.cpp, and ViewProviderSketch.
*
*/
Sketcher::GeoElementId getGeoElementIdFromVertexId(int vertexId);
@@ -175,31 +198,38 @@ public:
/** @brief
* Given an GeoElementId {GeoId, Pos}, it returns the index of the vertex in VertexId format.
*
* A vertexId is a positive index of the vertex, where indices of external geometry taken higher positive values than normal geometry.
* It is the same format of vertex numbering used in the Sketcher, Sketch.cpp, and ViewProviderSketch.
* A vertexId is a positive index of the vertex, where indices of external geometry taken higher
* positive values than normal geometry. It is the same format of vertex numbering used in the
* Sketcher, Sketch.cpp, and ViewProviderSketch.
*
*/
int getVertexIdFromGeoElementId(const Sketcher::GeoElementId & geoelementId) const;
int getVertexIdFromGeoElementId(const Sketcher::GeoElementId& geoelementId) const;
/** @brief
* Returns a point coordinates given {GeoId, Pos}.
*/
Vector3d getPoint(int geoId, Sketcher::PointPos pos) const;
/** @brief
/** @brief
* Returns a point coordinates given GeoElementId {GeoId, Pos}.
*/
Vector3d getPoint(const GeoElementId & geid) const;
Vector3d getPoint(const GeoElementId& geid) const;
/** @brief
* returns the amount of internal (normal, non-external) geometry objects.
*/
int getInternalCount() const { return intGeoCount;}
* returns the amount of internal (normal, non-external) geometry objects.
*/
int getInternalCount() const
{
return intGeoCount;
}
/** @brief
* returns the amount of external geometry objects.
*/
int getExternalCount() const { return int(geomlist.size()) - intGeoCount;}
* returns the amount of external geometry objects.
*/
int getExternalCount() const
{
return int(geomlist.size()) - intGeoCount;
}
/** @brief
* return a reference to the internal geometry list vector.
@@ -207,13 +237,16 @@ public:
* @warning { It returns a reference to the internal list vector. The validity of the
* reference depends on the lifetime of the GeoListModel object.}
*/
std::vector<T> & geometryList() { return const_cast<std::vector<T> &>(geomlist);}
std::vector<T>& geometryList()
{
return const_cast<std::vector<T>&>(geomlist);
}
public:
std::vector<T> geomlist;
private:
Vector3d getPoint(const Part::Geometry * geo, Sketcher::PointPos pos) const;
Vector3d getPoint(const Part::Geometry* geo, Sketcher::PointPos pos) const;
void rebuildVertexIndex() const;
@@ -221,20 +254,20 @@ private:
int intGeoCount;
bool OwnerT;
mutable bool indexInit;
mutable std::vector<Sketcher::GeoElementId> VertexId2GeoElementId; // these maps a lazy initialised on first demand.
mutable std::vector<Sketcher::GeoElementId>
VertexId2GeoElementId;// these maps a lazy initialised on first demand.
mutable std::map<Sketcher::GeoElementId, int> GeoElementId2VertexId;
};
using GeometryPtr = Part::Geometry *;
using GeometryPtr = Part::Geometry*;
using GeometryFacadeUniquePtr = std::unique_ptr<const Sketcher::GeometryFacade>;
using GeoList = GeoListModel<GeometryPtr>;
using GeoListFacade = GeoListModel<GeometryFacadeUniquePtr>;
GeoListFacade getGeoListFacade(const GeoList & geolist);
GeoListFacade getGeoListFacade(const GeoList& geolist);
} // namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_GeoList_H
#endif// SKETCHER_GeoList_H

View File

@@ -22,7 +22,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_io.hpp>
#endif
#include "GeometryFacade.h"
@@ -31,17 +31,19 @@
using namespace Sketcher;
TYPESYSTEM_SOURCE(Sketcher::GeometryFacade,Base::BaseClass)
TYPESYSTEM_SOURCE(Sketcher::GeometryFacade, Base::BaseClass)
GeometryFacade::GeometryFacade(): Geo(nullptr), OwnerGeo(false), SketchGeoExtension(nullptr)
GeometryFacade::GeometryFacade()
: Geo(nullptr),
OwnerGeo(false),
SketchGeoExtension(nullptr)
{}
GeometryFacade::GeometryFacade(const Part::Geometry* geometry, bool owner)
: Geo(geometry),
OwnerGeo(owner)
{
}
GeometryFacade::GeometryFacade(const Part::Geometry * geometry, bool owner)
: Geo(geometry), OwnerGeo(owner)
{
assert(geometry); // This should never be nullptr, as this constructor is protected
assert(geometry);// This should never be nullptr, as this constructor is protected
initExtension();
}
@@ -52,29 +54,31 @@ GeometryFacade::~GeometryFacade()
delete Geo;
}
std::unique_ptr<GeometryFacade> GeometryFacade::getFacade(Part::Geometry * geometry, bool owner)
std::unique_ptr<GeometryFacade> GeometryFacade::getFacade(Part::Geometry* geometry, bool owner)
{
if(geometry)
if (geometry)
return std::unique_ptr<GeometryFacade>(new GeometryFacade(geometry, owner));
else
return std::unique_ptr<GeometryFacade>(nullptr);
//return std::make_unique<GeometryFacade>(geometry); // make_unique has no access to private constructor
// make_unique has no access to private constructor
// return std::make_unique<GeometryFacade>(geometry);
}
std::unique_ptr<const GeometryFacade> GeometryFacade::getFacade(const Part::Geometry * geometry)
std::unique_ptr<const GeometryFacade> GeometryFacade::getFacade(const Part::Geometry* geometry)
{
if(geometry)
if (geometry)
return std::unique_ptr<const GeometryFacade>(new GeometryFacade(geometry));
else
else
return std::unique_ptr<const GeometryFacade>(nullptr);
//return std::make_unique<const GeometryFacade>(geometry); // make_unique has no access to private constructor
// make_unique has no access to private constructor
// return std::make_unique<const GeometryFacade>(geometry);
}
void GeometryFacade::setGeometry(Part::Geometry *geometry)
void GeometryFacade::setGeometry(Part::Geometry* geometry)
{
Geo = geometry;
if(geometry)
if (geometry)
initExtension();
else
THROWM(Base::ValueError, "GeometryFacade initialized with Geometry null pointer");
@@ -82,46 +86,48 @@ void GeometryFacade::setGeometry(Part::Geometry *geometry)
void GeometryFacade::initExtension()
{
if(!Geo->hasExtension(SketchGeometryExtension::getClassTypeId())) {
if (!Geo->hasExtension(SketchGeometryExtension::getClassTypeId())) {
getGeo()->setExtension(std::make_unique<SketchGeometryExtension>()); // Create getExtension
getGeo()->setExtension(std::make_unique<SketchGeometryExtension>());// Create getExtension
//Base::Console().Warning("%s\nSketcher Geometry without Extension: %s \n", boost::uuids::to_string(Geo->getTag()).c_str());
// Base::Console().Warning("%s\nSketcher Geometry without Extension: %s \n",
// boost::uuids::to_string(Geo->getTag()).c_str());
}
SketchGeoExtension =
std::static_pointer_cast<const SketchGeometryExtension>(
(Geo->getExtension(SketchGeometryExtension::getClassTypeId())).lock()
);
SketchGeoExtension = std::static_pointer_cast<const SketchGeometryExtension>(
(Geo->getExtension(SketchGeometryExtension::getClassTypeId())).lock());
}
void GeometryFacade::initExtension() const
{
// const Geometry without SketchGeometryExtension cannot initialise a GeometryFacade
if(!Geo->hasExtension(SketchGeometryExtension::getClassTypeId()))
THROWM(Base::ValueError, "Cannot create a GeometryFacade out of a const Geometry pointer not having a SketchGeometryExtension!");
if (!Geo->hasExtension(SketchGeometryExtension::getClassTypeId()))
THROWM(Base::ValueError,
"Cannot create a GeometryFacade out of a const Geometry pointer not having a "
"SketchGeometryExtension!");
auto ext = std::static_pointer_cast<const SketchGeometryExtension>(Geo->getExtension(SketchGeometryExtension::getClassTypeId()).lock());
auto ext = std::static_pointer_cast<const SketchGeometryExtension>(
Geo->getExtension(SketchGeometryExtension::getClassTypeId()).lock());
const_cast<GeometryFacade *>(this)->SketchGeoExtension = ext;
const_cast<GeometryFacade*>(this)->SketchGeoExtension = ext;
}
void GeometryFacade::throwOnNullPtr(const Part::Geometry * geo)
void GeometryFacade::throwOnNullPtr(const Part::Geometry* geo)
{
if(!geo)
if (!geo)
THROWM(Base::ValueError, "Geometry is nullptr!");
}
void GeometryFacade::ensureSketchGeometryExtension(Part::Geometry * geometry)
void GeometryFacade::ensureSketchGeometryExtension(Part::Geometry* geometry)
{
throwOnNullPtr(geometry);
if(!geometry->hasExtension(SketchGeometryExtension::getClassTypeId())) {
geometry->setExtension(std::make_unique<SketchGeometryExtension>()); // Create getExtension
if (!geometry->hasExtension(SketchGeometryExtension::getClassTypeId())) {
geometry->setExtension(std::make_unique<SketchGeometryExtension>());// Create getExtension
}
}
void GeometryFacade::copyId(const Part::Geometry * src, Part::Geometry * dst)
void GeometryFacade::copyId(const Part::Geometry* src, Part::Geometry* dst)
{
throwOnNullPtr(src);
throwOnNullPtr(dst);
@@ -131,7 +137,7 @@ void GeometryFacade::copyId(const Part::Geometry * src, Part::Geometry * dst)
gfdst->setId(gfsrc->getId());
}
bool GeometryFacade::getConstruction(const Part::Geometry * geometry)
bool GeometryFacade::getConstruction(const Part::Geometry* geometry)
{
throwOnNullPtr(geometry);
@@ -139,7 +145,7 @@ bool GeometryFacade::getConstruction(const Part::Geometry * geometry)
return gf->getConstruction();
}
void GeometryFacade::setConstruction(Part::Geometry * geometry, bool construction)
void GeometryFacade::setConstruction(Part::Geometry* geometry, bool construction)
{
throwOnNullPtr(geometry);
@@ -147,7 +153,7 @@ void GeometryFacade::setConstruction(Part::Geometry * geometry, bool constructio
return gf->setConstruction(construction);
}
bool GeometryFacade::isInternalType(const Part::Geometry * geometry, InternalType::InternalType type)
bool GeometryFacade::isInternalType(const Part::Geometry* geometry, InternalType::InternalType type)
{
throwOnNullPtr(geometry);
@@ -155,7 +161,7 @@ bool GeometryFacade::isInternalType(const Part::Geometry * geometry, InternalTyp
return gf->getInternalType() == type;
}
bool GeometryFacade::isInternalAligned(const Part::Geometry * geometry)
bool GeometryFacade::isInternalAligned(const Part::Geometry* geometry)
{
throwOnNullPtr(geometry);
@@ -163,7 +169,7 @@ bool GeometryFacade::isInternalAligned(const Part::Geometry * geometry)
return gf->isInternalAligned();
}
bool GeometryFacade::getBlocked(const Part::Geometry * geometry)
bool GeometryFacade::getBlocked(const Part::Geometry* geometry)
{
throwOnNullPtr(geometry);
@@ -171,7 +177,7 @@ bool GeometryFacade::getBlocked(const Part::Geometry * geometry)
return gf->getBlocked();
}
PyObject * GeometryFacade::getPyObject()
PyObject* GeometryFacade::getPyObject()
{
return new GeometryFacadePy(new GeometryFacade(this->Geo));
}

View File

@@ -34,29 +34,34 @@ namespace Sketcher
{
class GeometryFacadePy;
/** @brief This class is a Facade to handle geometry and sketcher geometry extensions with a single sketcher specific interface
/** @brief This class is a Facade to handle geometry and sketcher geometry extensions with a single
* sketcher specific interface
*
* @details
* The facade privately inherits from a common interface it shares with the extension thereby implementing a compiler enforced
* same interface as the extension. It does not inherit from Part::Geometry and thus is intended to provide, in part a convenience
* subset of the interface of Part::Geometry, in part a different interface.
* The facade privately inherits from a common interface it shares with the extension thereby
* implementing a compiler enforced same interface as the extension. It does not inherit from
* Part::Geometry and thus is intended to provide, in part a convenience subset of the interface of
* Part::Geometry, in part a different interface.
*
* GeometryFacade has private constructors and objects may only be created using the getFacade factory methods.
* GeometryFacade has private constructors and objects may only be created using the getFacade
* factory methods.
*
* There is a version of getFacade taking a const Part::Geometry and producing a const GeometryFacade, and a non-const
* version producing a non-const GeometryFacade. So constness of the Part::Geometry object is preserved by the GeometryFacade
* container.
* There is a version of getFacade taking a const Part::Geometry and producing a const
* GeometryFacade, and a non-const version producing a non-const GeometryFacade. So constness of the
* Part::Geometry object is preserved by the GeometryFacade container.
*
* There are some static convenience utility functions to simplify common operations such as ID copy or to ensure that a geometry
* object has the extension (creating the extension if not existing).
* There are some static convenience utility functions to simplify common operations such as ID copy
* or to ensure that a geometry object has the extension (creating the extension if not existing).
*
* @warning
* The const factory method will throw if the geometry does not have a SketchGeometryExtension (being const, it commits not to
* create one and modify the const Part::Geometry object). The non-const factory method will create the extension if not existing.
* The const factory method will throw if the geometry does not have a SketchGeometryExtension
* (being const, it commits not to create one and modify the const Part::Geometry object). The
* non-const factory method will create the extension if not existing.
*
* @warning
* If the Geometry Pointer fed into the factory method is a nullptr, a nullptr GeometryFacade is created. It should not be possible
* to create a GeometryFacade having a Part::Geometry * being a nullptr.
* If the Geometry Pointer fed into the factory method is a nullptr, a nullptr GeometryFacade is
* created. It should not be possible to create a GeometryFacade having a Part::Geometry * being a
* nullptr.
*
* A simple usage example:
*
@@ -86,43 +91,44 @@ class GeometryFacadePy;
* GeometryFacade::setConstruction(copy, construction);
* }
*
* Note: The standard GeometryFacade stores Part::Geometry derived classes as a Part::Geometry *, while
* it has the ability to return a dynamic_cast-ed version to a provided type as follows:
* Note: The standard GeometryFacade stores Part::Geometry derived classes as a Part::Geometry *,
* while it has the ability to return a dynamic_cast-ed version to a provided type as follows:
*
* HLine->getGeometry<Part::GeomLineSegment>();
*
* If for seamless operation it is convenient to have a given derived class of Part::Geometry, it is possible
* to use GeometryTypedFacade (see below).
* If for seamless operation it is convenient to have a given derived class of Part::Geometry, it is
* possible to use GeometryTypedFacade (see below).
*
* @remarks
* Summary Remarks:
* It is intended to have a separate type (not being a Geometry type).
* it is intended to have the relevant interface in full for the sketcher extension only
* It is intended to work on borrowed memory allocation. But the getFacade has an owner parameter to take ownership of the
* geometry pointer if that is intended (this can also be achieved via the setOwner method once created).
* It is intended to work on borrowed memory allocation. But the getFacade has an owner parameter to
* take ownership of the geometry pointer if that is intended (this can also be achieved via the
* setOwner method once created).
*/
class SketcherExport GeometryFacade : public Base::BaseClass, private ISketchGeometryExtension
class SketcherExport GeometryFacade: public Base::BaseClass, private ISketchGeometryExtension
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER_WITH_OVERRIDE();
protected:
explicit GeometryFacade(const Part::Geometry * geometry, bool owner = false);
GeometryFacade(); // As TYPESYSTEM requirement
explicit GeometryFacade(const Part::Geometry* geometry, bool owner = false);
GeometryFacade();// As TYPESYSTEM requirement
friend class GeometryFacadePy;
public: // Factory methods
static std::unique_ptr<GeometryFacade> getFacade(Part::Geometry * geometry, bool owner = false);
static std::unique_ptr<const GeometryFacade> getFacade(const Part::Geometry * geometry);
public:// Factory methods
static std::unique_ptr<GeometryFacade> getFacade(Part::Geometry* geometry, bool owner = false);
static std::unique_ptr<const GeometryFacade> getFacade(const Part::Geometry* geometry);
public: // Utility methods
static void ensureSketchGeometryExtension(Part::Geometry * geometry);
static void copyId(const Part::Geometry * src, Part::Geometry * dst);
static bool getConstruction(const Part::Geometry * geometry);
static void setConstruction(Part::Geometry * geometry, bool construction);
static bool isInternalType(const Part::Geometry * geometry, InternalType::InternalType type);
public:// Utility methods
static void ensureSketchGeometryExtension(Part::Geometry* geometry);
static void copyId(const Part::Geometry* src, Part::Geometry* dst);
static bool getConstruction(const Part::Geometry* geometry);
static void setConstruction(Part::Geometry* geometry, bool construction);
static bool isInternalType(const Part::Geometry* geometry, InternalType::InternalType type);
static bool isInternalAligned(const Part::Geometry* geometry);
static bool getBlocked(const Part::Geometry * geometry);
static bool getBlocked(const Part::Geometry* geometry);
public:
// Explicit deletion to show intent (not that it is needed)
@@ -133,108 +139,228 @@ public:
GeometryFacade& operator=(GeometryFacade&&) = default;
~GeometryFacade() override;
void setGeometry(Part::Geometry *geometry);
void setGeometry(Part::Geometry* geometry);
void setOwner(bool owner) {
void setOwner(bool owner)
{
OwnerGeo = owner;
}
// returns if the facade is the owner of the geometry pointer.
bool getOwner() const {
bool getOwner() const
{
return OwnerGeo;
}
// Geometry Extension Interface
inline long getId() const override {return getGeoExt()->getId();}
void setId(long id) override {getGeoExt()->setId(id);}
inline long getId() const override
{
return getGeoExt()->getId();
}
void setId(long id) override
{
getGeoExt()->setId(id);
}
InternalType::InternalType getInternalType() const override {return getGeoExt()->getInternalType();}
void setInternalType(InternalType::InternalType type) override {getGeoExt()->setInternalType(type);}
InternalType::InternalType getInternalType() const override
{
return getGeoExt()->getInternalType();
}
void setInternalType(InternalType::InternalType type) override
{
getGeoExt()->setInternalType(type);
}
bool testGeometryMode(int flag) const override { return getGeoExt()->testGeometryMode(flag); }
void setGeometryMode(int flag, bool v=true) override { getGeoExt()->setGeometryMode(flag, v); }
bool testGeometryMode(int flag) const override
{
return getGeoExt()->testGeometryMode(flag);
}
void setGeometryMode(int flag, bool v = true) override
{
getGeoExt()->setGeometryMode(flag, v);
}
int getGeometryLayerId() const override { return getGeoExt()->getGeometryLayerId();}
void setGeometryLayerId(int geolayer) override { getGeoExt()->setGeometryLayerId(geolayer);}
int getGeometryLayerId() const override
{
return getGeoExt()->getGeometryLayerId();
}
void setGeometryLayerId(int geolayer) override
{
getGeoExt()->setGeometryLayerId(geolayer);
}
// Convenience accessor
bool getBlocked() const { return this->testGeometryMode(GeometryMode::Blocked);}
void setBlocked(bool status = true) {this->setGeometryMode(GeometryMode::Blocked, status);}
bool getBlocked() const
{
return this->testGeometryMode(GeometryMode::Blocked);
}
void setBlocked(bool status = true)
{
this->setGeometryMode(GeometryMode::Blocked, status);
}
inline bool getConstruction() const {return this->testGeometryMode(GeometryMode::Construction);}
inline void setConstruction(bool construction) {this->setGeometryMode(GeometryMode::Construction, construction);}
inline bool getConstruction() const
{
return this->testGeometryMode(GeometryMode::Construction);
}
inline void setConstruction(bool construction)
{
this->setGeometryMode(GeometryMode::Construction, construction);
}
bool isInternalAligned() const { return this->getInternalType() != InternalType::None; }
bool isInternalAligned() const
{
return this->getInternalType() != InternalType::None;
}
bool isInternalType(InternalType::InternalType type) const { return this->getInternalType() == type; }
bool isInternalType(InternalType::InternalType type) const
{
return this->getInternalType() == type;
}
// Geometry Extension Information
inline const std::string &getExtensionName () const {return SketchGeoExtension->getName();}
inline const std::string& getExtensionName() const
{
return SketchGeoExtension->getName();
}
// Geometry Element
template < typename GeometryT = Part::Geometry,
typename = typename std::enable_if<
std::is_base_of<Part::Geometry, typename std::decay<GeometryT>::type>::value
>::type
>
GeometryT * getGeometry() {return dynamic_cast<GeometryT *>(const_cast<Part::Geometry *>(Geo));}
template<typename GeometryT = Part::Geometry,
typename = typename std::enable_if<std::is_base_of<
Part::Geometry, typename std::decay<GeometryT>::type>::value>::type>
GeometryT* getGeometry()
{
return dynamic_cast<GeometryT*>(const_cast<Part::Geometry*>(Geo));
}
// Geometry Element
template < typename GeometryT = Part::Geometry,
typename = typename std::enable_if<
std::is_base_of<Part::Geometry, typename std::decay<GeometryT>::type>::value
>::type
>
const GeometryT * getGeometry() const {return dynamic_cast<const GeometryT *>(Geo);}
template<typename GeometryT = Part::Geometry,
typename = typename std::enable_if<std::is_base_of<
Part::Geometry, typename std::decay<GeometryT>::type>::value>::type>
const GeometryT* getGeometry() const
{
return dynamic_cast<const GeometryT*>(Geo);
}
PyObject *getPyObject() override;
PyObject* getPyObject() override;
// Geometry Interface
TopoDS_Shape toShape() const {return getGeo()->toShape();}
const Handle(Geom_Geometry)& handle() const {return getGeo()->handle();}
Part::Geometry *copy() const {return getGeo()->copy();}
Part::Geometry *clone() const {return getGeo()->clone();}
boost::uuids::uuid getTag() const {return getGeo()->getTag();}
TopoDS_Shape toShape() const
{
return getGeo()->toShape();
}
const Handle(Geom_Geometry) & handle() const
{
return getGeo()->handle();
}
Part::Geometry* copy() const
{
return getGeo()->copy();
}
Part::Geometry* clone() const
{
return getGeo()->clone();
}
boost::uuids::uuid getTag() const
{
return getGeo()->getTag();
}
std::vector<std::weak_ptr<const Part::GeometryExtension>> getExtensions() const {return getGeo()->getExtensions();}
bool hasExtension(const Base::Type & type) const {return getGeo()->hasExtension(type);}
bool hasExtension(const std::string & name) const {return getGeo()->hasExtension(name);}
std::weak_ptr<const Part::GeometryExtension> getExtension(const Base::Type & type) const {return getGeo()->getExtension(type);}
std::weak_ptr<const Part::GeometryExtension> getExtension(const std::string & name) const {return getGeo()->getExtension(name);}
void setExtension(std::unique_ptr<Part::GeometryExtension> &&geo) {return getGeo()->setExtension(std::move(geo));}
void deleteExtension(const Base::Type & type) {return getGeo()->deleteExtension(type);}
void deleteExtension(const std::string & name) {return getGeo()->deleteExtension(name);}
std::vector<std::weak_ptr<const Part::GeometryExtension>> getExtensions() const
{
return getGeo()->getExtensions();
}
bool hasExtension(const Base::Type& type) const
{
return getGeo()->hasExtension(type);
}
bool hasExtension(const std::string& name) const
{
return getGeo()->hasExtension(name);
}
std::weak_ptr<const Part::GeometryExtension> getExtension(const Base::Type& type) const
{
return getGeo()->getExtension(type);
}
std::weak_ptr<const Part::GeometryExtension> getExtension(const std::string& name) const
{
return getGeo()->getExtension(name);
}
void setExtension(std::unique_ptr<Part::GeometryExtension>&& geo)
{
return getGeo()->setExtension(std::move(geo));
}
void deleteExtension(const Base::Type& type)
{
return getGeo()->deleteExtension(type);
}
void deleteExtension(const std::string& name)
{
return getGeo()->deleteExtension(name);
}
void mirror(const Base::Vector3d & point) {return getGeo()->mirror(point);}
void mirror(const Base::Vector3d & point, Base::Vector3d dir) {return getGeo()->mirror(point, dir);}
void rotate(const Base::Placement & plm) {return getGeo()->rotate(plm);}
void scale(const Base::Vector3d & vec, double scale) {return getGeo()->scale(vec, scale);}
void transform(const Base::Matrix4D & mat) {return getGeo()->transform(mat);}
void translate(const Base::Vector3d & vec) {return getGeo()->translate(vec);}
void mirror(const Base::Vector3d& point)
{
return getGeo()->mirror(point);
}
void mirror(const Base::Vector3d& point, Base::Vector3d dir)
{
return getGeo()->mirror(point, dir);
}
void rotate(const Base::Placement& plm)
{
return getGeo()->rotate(plm);
}
void scale(const Base::Vector3d& vec, double scale)
{
return getGeo()->scale(vec, scale);
}
void transform(const Base::Matrix4D& mat)
{
return getGeo()->transform(mat);
}
void translate(const Base::Vector3d& vec)
{
return getGeo()->translate(vec);
}
// convenience GeometryFunctions
bool isGeoType(const Base::Type &type) const { return getGeo()->getTypeId() == type;}
bool isGeoType(const Base::Type& type) const
{
return getGeo()->getTypeId() == type;
}
private:
void initExtension();
void initExtension() const;
const Part::Geometry * getGeo() const {return Geo;}
Part::Geometry * getGeo() {return const_cast<Part::Geometry *>(Geo);}
const Part::Geometry* getGeo() const
{
return Geo;
}
Part::Geometry* getGeo()
{
return const_cast<Part::Geometry*>(Geo);
}
std::shared_ptr<const SketchGeometryExtension> getGeoExt() const {return SketchGeoExtension;}
std::shared_ptr<SketchGeometryExtension> getGeoExt () {return std::const_pointer_cast<SketchGeometryExtension>(SketchGeoExtension);}
std::shared_ptr<const SketchGeometryExtension> getGeoExt() const
{
return SketchGeoExtension;
}
std::shared_ptr<SketchGeometryExtension> getGeoExt()
{
return std::const_pointer_cast<SketchGeometryExtension>(SketchGeoExtension);
}
static void throwOnNullPtr(const Part::Geometry * geo);
static void throwOnNullPtr(const Part::Geometry* geo);
private:
const Part::Geometry * Geo;
const Part::Geometry* Geo;
bool OwnerGeo;
std::shared_ptr<const SketchGeometryExtension> SketchGeoExtension;
};
///////////////////////////////////////////////////////////////////////////////////////
//
// GeometryTypedFacade
@@ -251,8 +377,8 @@ private:
* HLine->getTypedGeometry()->setPoints(Base::Vector3d(0,0,0),Base::Vector3d(1,0,0));
*
* If a facade is requested without passing an Part::Geometry derived object, the constructor
* of the indicated geometry type is called with any parameter passed as argument (emplace style). In
* this case the facade takes ownership of the newly created Part::Geometry object.
* of the indicated geometry type is called with any parameter passed as argument (emplace style).
* In this case the facade takes ownership of the newly created Part::Geometry object.
*
* Example of seamless operation with a GeomLineSegment:
*
@@ -261,27 +387,39 @@ private:
* HLine->setConstruction(true);
* ExternalGeo.push_back(HLine->getGeometry());
*/
template < typename GeometryT >
class SketcherExport GeometryTypedFacade : public GeometryFacade
template<typename GeometryT>
class SketcherExport GeometryTypedFacade: public GeometryFacade
{
static_assert( std::is_base_of<Part::Geometry, typename std::decay<GeometryT>::type>::value &&
!std::is_same<Part::Geometry, typename std::decay<GeometryT>::type>::value, "Only for classes derived from Geometry!");
private:
explicit GeometryTypedFacade(const Part::Geometry * geometry, bool owner = false):GeometryFacade(geometry, owner) {}
GeometryTypedFacade():GeometryFacade() {}
static_assert(std::is_base_of<Part::Geometry, typename std::decay<GeometryT>::type>::value
&& !std::is_same<Part::Geometry, typename std::decay<GeometryT>::type>::value,
"Only for classes derived from Geometry!");
public: // Factory methods
static std::unique_ptr<GeometryTypedFacade<GeometryT>> getTypedFacade(GeometryT * geometry, bool owner = false) {
if(geometry) {
return std::unique_ptr<GeometryTypedFacade<GeometryT>>(new GeometryTypedFacade(geometry, owner));
private:
explicit GeometryTypedFacade(const Part::Geometry* geometry, bool owner = false)
: GeometryFacade(geometry, owner)
{}
GeometryTypedFacade()
: GeometryFacade()
{}
public:// Factory methods
static std::unique_ptr<GeometryTypedFacade<GeometryT>> getTypedFacade(GeometryT* geometry,
bool owner = false)
{
if (geometry) {
return std::unique_ptr<GeometryTypedFacade<GeometryT>>(
new GeometryTypedFacade(geometry, owner));
}
else {
return std::unique_ptr<GeometryTypedFacade<GeometryT>>(nullptr);
}
}
static std::unique_ptr<const GeometryTypedFacade<GeometryT>> getTypedFacade(const GeometryT * geometry) {
if(geometry) {
return std::unique_ptr<const GeometryTypedFacade<GeometryT>>(new GeometryTypedFacade(geometry));
static std::unique_ptr<const GeometryTypedFacade<GeometryT>>
getTypedFacade(const GeometryT* geometry)
{
if (geometry) {
return std::unique_ptr<const GeometryTypedFacade<GeometryT>>(
new GeometryTypedFacade(geometry));
}
else {
return std::unique_ptr<const GeometryTypedFacade<GeometryT>>(nullptr);
@@ -289,23 +427,28 @@ public: // Factory methods
}
// This function takes direct ownership of the object it creates.
template < typename... Args >
static std::unique_ptr<GeometryTypedFacade<GeometryT>> getTypedFacade(Args&&... args) {
return GeometryTypedFacade::getTypedFacade(new GeometryT(std::forward<Args>(args)...), true);
template<typename... Args>
static std::unique_ptr<GeometryTypedFacade<GeometryT>> getTypedFacade(Args&&... args)
{
return GeometryTypedFacade::getTypedFacade(new GeometryT(std::forward<Args>(args)...),
true);
}
// Geometry Element
GeometryT * getTypedGeometry() {return GeometryFacade::getGeometry<GeometryT>();}
GeometryT* getTypedGeometry()
{
return GeometryFacade::getGeometry<GeometryT>();
}
// Geometry Element
GeometryT * getTypedGeometry() const {return GeometryFacade::getGeometry<GeometryT>();}
GeometryT* getTypedGeometry() const
{
return GeometryFacade::getGeometry<GeometryT>();
}
};
}// namespace Sketcher
} //namespace Sketcher
#endif // SKETCHER_GEOMETRYFACADE_H
#endif// SKETCHER_GEOMETRYFACADE_H

View File

@@ -24,14 +24,15 @@
#include <Base/GeometryPyCXX.h>
#include <Base/MatrixPy.h>
#include <Base/PlacementPy.h>
#include <Base/Vector3D.h>
#include <Base/VectorPy.h>
#include <Base/PlacementPy.h>
#include <Mod/Part/App/GeometryExtensionPy.h>
#include <Mod/Part/App/GeometryPy.h>
#include <Mod/Part/App/OCCError.h>
#include "GeometryFacadePy.h"
#include "GeometryFacadePy.cpp"
@@ -47,7 +48,7 @@ std::string GeometryFacadePy::representation() const
return str.str();
}
PyObject *GeometryFacadePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
PyObject* GeometryFacadePy::PyMake(struct _typeobject*, PyObject*, PyObject*)// Python wrapper
{
// create a new instance of PointPy and the Twin object
return new GeometryFacadePy(new GeometryFacade());
@@ -56,18 +57,18 @@ PyObject *GeometryFacadePy::PyMake(struct _typeobject *, PyObject *, PyObject *)
// constructor method
int GeometryFacadePy::PyInit(PyObject* args, PyObject* /*kwd*/)
{
PyObject *object;
if (PyArg_ParseTuple(args,"O!",&(Part::GeometryPy::Type), &object)) {
Part::Geometry * geo = static_cast<Part::GeometryPy *>(object)->getGeometryPtr();
PyObject* object;
if (PyArg_ParseTuple(args, "O!", &(Part::GeometryPy::Type), &object)) {
Part::Geometry* geo = static_cast<Part::GeometryPy*>(object)->getGeometryPtr();
getGeometryFacadePtr()->setGeometry(geo->clone());
return 0;
}
PyErr_SetString(PyExc_TypeError, "Sketcher::GeometryFacade constructor accepts:\n"
"-- Part.Geometry\n"
);
PyErr_SetString(PyExc_TypeError,
"Sketcher::GeometryFacade constructor accepts:\n"
"-- Part.Geometry\n");
return -1;
}
@@ -85,12 +86,12 @@ Py::String GeometryFacadePy::getInternalType() const
{
int internaltypeindex = (int)this->getGeometryFacadePtr()->getInternalType();
if(internaltypeindex >= InternalType::NumInternalGeometryType)
if (internaltypeindex >= InternalType::NumInternalGeometryType)
throw Py::NotImplementedError("String name of enum not implemented");
std::string typestr = SketchGeometryExtension::internaltype2str[internaltypeindex];
return Py::String(typestr);
return Py::String(typestr);
}
void GeometryFacadePy::setInternalType(Py::String arg)
@@ -98,7 +99,7 @@ void GeometryFacadePy::setInternalType(Py::String arg)
std::string argstr = arg;
InternalType::InternalType type;
if(SketchGeometryExtension::getInternalTypeFromName(argstr, type)) {
if (SketchGeometryExtension::getInternalTypeFromName(argstr, type)) {
this->getGeometryFacadePtr()->setInternalType(type);
return;
}
@@ -116,14 +117,14 @@ void GeometryFacadePy::setBlocked(Py::Boolean arg)
getGeometryFacadePtr()->setBlocked(arg);
}
PyObject* GeometryFacadePy::testGeometryMode(PyObject *args)
PyObject* GeometryFacadePy::testGeometryMode(PyObject* args)
{
char* flag;
if (PyArg_ParseTuple(args, "s",&flag)) {
if (PyArg_ParseTuple(args, "s", &flag)) {
GeometryMode::GeometryMode mode;
if(SketchGeometryExtension::getGeometryModeFromName(flag, mode))
if (SketchGeometryExtension::getGeometryModeFromName(flag, mode))
return new_reference_to(Py::Boolean(getGeometryFacadePtr()->testGeometryMode(mode)));
PyErr_SetString(PyExc_TypeError, "Flag string does not exist.");
@@ -134,15 +135,15 @@ PyObject* GeometryFacadePy::testGeometryMode(PyObject *args)
return nullptr;
}
PyObject* GeometryFacadePy::setGeometryMode(PyObject *args)
PyObject* GeometryFacadePy::setGeometryMode(PyObject* args)
{
char * flag;
PyObject * bflag = Py_True;
char* flag;
PyObject* bflag = Py_True;
if (PyArg_ParseTuple(args, "s|O!", &flag, &PyBool_Type, &bflag)) {
GeometryMode::GeometryMode mode;
if(SketchGeometryExtension::getGeometryModeFromName(flag, mode)) {
if (SketchGeometryExtension::getGeometryModeFromName(flag, mode)) {
getGeometryFacadePtr()->setGeometryMode(mode, Base::asBoolean(bflag));
Py_Return;
}
@@ -156,10 +157,10 @@ PyObject* GeometryFacadePy::setGeometryMode(PyObject *args)
}
PyObject* GeometryFacadePy::mirror(PyObject *args)
PyObject* GeometryFacadePy::mirror(PyObject* args)
{
PyObject* o;
if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&o)) {
if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &o)) {
Base::Vector3d vec = static_cast<Base::VectorPy*>(o)->value();
getGeometryFacadePtr()->mirror(vec);
Py_Return;
@@ -167,22 +168,23 @@ PyObject* GeometryFacadePy::mirror(PyObject *args)
PyErr_Clear();
PyObject* axis;
if (PyArg_ParseTuple(args, "O!O!", &(Base::VectorPy::Type),&o,
&(Base::VectorPy::Type),&axis)) {
if (PyArg_ParseTuple(
args, "O!O!", &(Base::VectorPy::Type), &o, &(Base::VectorPy::Type), &axis)) {
Base::Vector3d pnt = static_cast<Base::VectorPy*>(o)->value();
Base::Vector3d dir = static_cast<Base::VectorPy*>(axis)->value();
getGeometryFacadePtr()->mirror(pnt, dir);
Py_Return;
}
PyErr_SetString(Part::PartExceptionOCCError, "either a point (vector) or axis (vector, vector) must be given");
PyErr_SetString(Part::PartExceptionOCCError,
"either a point (vector) or axis (vector, vector) must be given");
return nullptr;
}
PyObject* GeometryFacadePy::rotate(PyObject *args)
PyObject* GeometryFacadePy::rotate(PyObject* args)
{
PyObject* o;
if (!PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type),&o))
if (!PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &o))
return nullptr;
Base::Placement* plm = static_cast<Base::PlacementPy*>(o)->getPlacementPtr();
@@ -190,19 +192,19 @@ PyObject* GeometryFacadePy::rotate(PyObject *args)
Py_Return;
}
PyObject* GeometryFacadePy::scale(PyObject *args)
PyObject* GeometryFacadePy::scale(PyObject* args)
{
PyObject* o;
double scale;
Base::Vector3d vec;
if (PyArg_ParseTuple(args, "O!d", &(Base::VectorPy::Type),&o, &scale)) {
if (PyArg_ParseTuple(args, "O!d", &(Base::VectorPy::Type), &o, &scale)) {
vec = static_cast<Base::VectorPy*>(o)->value();
getGeometryFacadePtr()->scale(vec, scale);
Py_Return;
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O!d", &PyTuple_Type,&o, &scale)) {
if (PyArg_ParseTuple(args, "O!d", &PyTuple_Type, &o, &scale)) {
vec = Base::getVectorFromTuple<double>(o);
getGeometryFacadePtr()->scale(vec, scale);
Py_Return;
@@ -212,28 +214,28 @@ PyObject* GeometryFacadePy::scale(PyObject *args)
return nullptr;
}
PyObject* GeometryFacadePy::transform(PyObject *args)
PyObject* GeometryFacadePy::transform(PyObject* args)
{
PyObject* o;
if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type),&o))
if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type), &o))
return nullptr;
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(o)->value();
getGeometryFacadePtr()->transform(mat);
Py_Return;
}
PyObject* GeometryFacadePy::translate(PyObject *args)
PyObject* GeometryFacadePy::translate(PyObject* args)
{
PyObject* o;
Base::Vector3d vec;
if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&o)) {
if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &o)) {
vec = static_cast<Base::VectorPy*>(o)->value();
getGeometryFacadePtr()->translate(vec);
Py_Return;
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O!", &PyTuple_Type,&o)) {
if (PyArg_ParseTuple(args, "O!", &PyTuple_Type, &o)) {
vec = Base::getVectorFromTuple<double>(o);
getGeometryFacadePtr()->translate(vec);
Py_Return;
@@ -243,12 +245,12 @@ PyObject* GeometryFacadePy::translate(PyObject *args)
return nullptr;
}
PyObject* GeometryFacadePy::setExtension(PyObject *args)
PyObject* GeometryFacadePy::setExtension(PyObject* args)
{
PyObject* o;
if (PyArg_ParseTuple(args, "O!", &(Part::GeometryExtensionPy::Type),&o)) {
Part::GeometryExtension * ext;
ext = static_cast<Part::GeometryExtensionPy *>(o)->getGeometryExtensionPtr();
if (PyArg_ParseTuple(args, "O!", &(Part::GeometryExtensionPy::Type), &o)) {
Part::GeometryExtension* ext;
ext = static_cast<Part::GeometryExtensionPy*>(o)->getGeometryExtensionPtr();
// make copy of Python managed memory and wrap it in smart pointer
auto cpy = ext->copy();
@@ -261,153 +263,159 @@ PyObject* GeometryFacadePy::setExtension(PyObject *args)
return nullptr;
}
PyObject* GeometryFacadePy::getExtensionOfType(PyObject *args)
PyObject* GeometryFacadePy::getExtensionOfType(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
Base::Type type = Base::Type::fromName(o);
if(type != Base::Type::badType()) {
if (type != Base::Type::badType()) {
try {
std::shared_ptr<const Part::GeometryExtension> ext(this->getGeometryFacadePtr()->getExtension(type));
std::shared_ptr<const Part::GeometryExtension> ext(
this->getGeometryFacadePtr()->getExtension(type));
// we create a copy and transfer this copy's memory management responsibility to Python
// we create a copy and transfer this copy's memory management responsibility to
// Python
PyObject* cpy = ext->copyPyObject();
return cpy;
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
catch(const std::bad_weak_ptr&) {
PyErr_SetString(Part::PartExceptionOCCError, "Geometry extension does not exist anymore.");
catch (const std::bad_weak_ptr&) {
PyErr_SetString(Part::PartExceptionOCCError,
"Geometry extension does not exist anymore.");
return nullptr;
}
catch(Base::NotImplementedError&) {
PyErr_SetString(Part::PartExceptionOCCError, "Geometry extension does not implement a Python counterpart.");
catch (Base::NotImplementedError&) {
PyErr_SetString(Part::PartExceptionOCCError,
"Geometry extension does not implement a Python counterpart.");
return nullptr;
}
}
else
{
else {
PyErr_SetString(Part::PartExceptionOCCError, "Exception type does not exist");
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the name of the geometry extension type was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the name of the geometry extension type was expected");
return nullptr;
}
PyObject* GeometryFacadePy::getExtensionOfName(PyObject *args)
PyObject* GeometryFacadePy::getExtensionOfName(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
try {
std::shared_ptr<const Part::GeometryExtension> ext(this->getGeometryFacadePtr()->getExtension(std::string(o)));
std::shared_ptr<const Part::GeometryExtension> ext(
this->getGeometryFacadePtr()->getExtension(std::string(o)));
// we create a copy and transfer this copy's memory management responsibility to Python
PyObject* cpy = ext->copyPyObject();
return cpy;
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
catch(const std::bad_weak_ptr&) {
PyErr_SetString(Part::PartExceptionOCCError, "Geometry extension does not exist anymore.");
catch (const std::bad_weak_ptr&) {
PyErr_SetString(Part::PartExceptionOCCError,
"Geometry extension does not exist anymore.");
return nullptr;
}
catch(Base::NotImplementedError&) {
PyErr_SetString(Part::PartExceptionOCCError, "Geometry extension does not implement a Python counterpart.");
catch (Base::NotImplementedError&) {
PyErr_SetString(Part::PartExceptionOCCError,
"Geometry extension does not implement a Python counterpart.");
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the name of the geometry extension was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the name of the geometry extension was expected");
return nullptr;
}
PyObject* GeometryFacadePy::hasExtensionOfType(PyObject *args)
PyObject* GeometryFacadePy::hasExtensionOfType(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
Base::Type type = Base::Type::fromName(o);
if(type != Base::Type::badType()) {
if (type != Base::Type::badType()) {
try {
return Py::new_reference_to(Py::Boolean(this->getGeometryFacadePtr()->hasExtension(type)));
return Py::new_reference_to(
Py::Boolean(this->getGeometryFacadePtr()->hasExtension(type)));
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
else
{
else {
PyErr_SetString(Part::PartExceptionOCCError, "Exception type does not exist");
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the type of the geometry extension was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the type of the geometry extension was expected");
return nullptr;
}
PyObject* GeometryFacadePy::hasExtensionOfName(PyObject *args)
PyObject* GeometryFacadePy::hasExtensionOfName(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
try {
return Py::new_reference_to(Py::Boolean(this->getGeometryFacadePtr()->hasExtension(std::string(o))));
return Py::new_reference_to(
Py::Boolean(this->getGeometryFacadePtr()->hasExtension(std::string(o))));
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the type of the geometry extension was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the type of the geometry extension was expected");
return nullptr;
}
PyObject* GeometryFacadePy::deleteExtensionOfType(PyObject *args)
PyObject* GeometryFacadePy::deleteExtensionOfType(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
Base::Type type = Base::Type::fromName(o);
if(type != Base::Type::badType()) {
if (type != Base::Type::badType()) {
try {
this->getGeometryFacadePtr()->deleteExtension(type);
Py_Return;
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
else
{
else {
PyErr_SetString(Part::PartExceptionOCCError, "Type does not exist");
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with a type object was expected");
return nullptr;
}
PyObject* GeometryFacadePy::deleteExtensionOfName(PyObject *args)
PyObject* GeometryFacadePy::deleteExtensionOfName(PyObject* args)
{
char* o;
if (PyArg_ParseTuple(args, "s", &o)) {
@@ -416,38 +424,40 @@ PyObject* GeometryFacadePy::deleteExtensionOfName(PyObject *args)
this->getGeometryFacadePtr()->deleteExtension(std::string(o));
Py_Return;
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
PyErr_SetString(Part::PartExceptionOCCError, "A string with the name of the extension was expected");
PyErr_SetString(Part::PartExceptionOCCError,
"A string with the name of the extension was expected");
return nullptr;
}
PyObject* GeometryFacadePy::getExtensions(PyObject *args)
PyObject* GeometryFacadePy::getExtensions(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")){
if (!PyArg_ParseTuple(args, "")) {
PyErr_SetString(Part::PartExceptionOCCError, "No arguments were expected");
return nullptr;
}
try {
const std::vector<std::weak_ptr<const Part::GeometryExtension>> ext = this->getGeometryFacadePtr()->getExtensions();
const std::vector<std::weak_ptr<const Part::GeometryExtension>> ext =
this->getGeometryFacadePtr()->getExtensions();
Py::List list;
for (std::size_t i=0; i<ext.size(); ++i) {
for (std::size_t i = 0; i < ext.size(); ++i) {
std::shared_ptr<const Part::GeometryExtension> p = ext[i].lock();
if(p) {
if (p) {
// we create a python copy and add it to the list
try {
list.append(Py::asObject(p->copyPyObject()));
}
catch(Base::NotImplementedError&) {
catch (Base::NotImplementedError&) {
// silently ignoring extensions not having a Python object
}
}
@@ -455,11 +465,10 @@ PyObject* GeometryFacadePy::getExtensions(PyObject *args)
return Py::new_reference_to(list);
}
catch(const Base::ValueError& e) {
catch (const Base::ValueError& e) {
PyErr_SetString(Part::PartExceptionOCCError, e.what());
return nullptr;
}
}
Py::Boolean GeometryFacadePy::getConstruction() const
@@ -467,7 +476,7 @@ Py::Boolean GeometryFacadePy::getConstruction() const
return Py::Boolean(getGeometryFacadePtr()->getConstruction());
}
void GeometryFacadePy::setConstruction(Py::Boolean arg)
void GeometryFacadePy::setConstruction(Py::Boolean arg)
{
getGeometryFacadePtr()->setConstruction(arg);
}
@@ -495,17 +504,17 @@ Py::Object GeometryFacadePy::getGeometry() const
return Py::Object(geo->getPyObject(), true);
}
void GeometryFacadePy::setGeometry(Py::Object arg)
void GeometryFacadePy::setGeometry(Py::Object arg)
{
if (PyObject_TypeCheck(arg.ptr(), &(Part::GeometryPy::Type))) {
Part::GeometryPy * gp = static_cast<Part::GeometryPy *>(arg.ptr());
Part::GeometryPy* gp = static_cast<Part::GeometryPy*>(arg.ptr());
getGeometryFacadePtr()->setGeometry(gp->getGeometryPtr()->clone());
}
}
PyObject *GeometryFacadePy::getCustomAttributes(const char* /*attr*/) const
PyObject* GeometryFacadePy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}

View File

@@ -21,4 +21,4 @@
***************************************************************************/
#include "PreCompiled.h"
#include "PreCompiled.h"

View File

@@ -43,15 +43,17 @@
#include <boost/uuid/uuid_io.hpp>
// OpenCasCade
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepOffsetAPI_NormalProjection.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <GC_MakeCircle.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
@@ -60,8 +62,19 @@
#include <Geom_Parabola.hxx>
#include <Geom_Plane.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
#include <Precision.hxx>
#include <ShapeFix_Wire.hxx>
#include <Standard_Version.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <gp_Ax3.hxx>
#include <gp_Circ.hxx>
#include <gp_Elips.hxx>
@@ -69,25 +82,12 @@
#include <gp_Parab.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <Precision.hxx>
#include <ShapeFix_Wire.hxx>
#include <Standard_Version.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#elif defined(FC_OS_WIN32)
#ifndef NOMINMAX
# define NOMINMAX
#define NOMINMAX
#endif
# include <windows.h>
#endif // _PreComp_
#include <windows.h>
#endif// _PreComp_
#endif

View File

@@ -22,18 +22,18 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cassert>
#include <cassert>
#endif
#include <App/ExpressionParser.h>
#include <App/ObjectIdentifier.h>
#include <Base/QuantityPy.h>
#include <Base/Reader.h>
#include <Base/Writer.h>
#include <Base/Tools.h>
#include <Base/Writer.h>
#include "PropertyConstraintList.h"
#include "ConstraintPy.h"
#include "PropertyConstraintList.h"
using namespace App;
@@ -52,32 +52,32 @@ TYPESYSTEM_SOURCE(Sketcher::PropertyConstraintList, App::PropertyLists)
PropertyConstraintList::PropertyConstraintList()
: validGeometryKeys(0)
, invalidGeometry(true)
, restoreFromTransaction(false)
, invalidIndices(false)
{
}
: validGeometryKeys(0),
invalidGeometry(true),
restoreFromTransaction(false),
invalidIndices(false)
{}
PropertyConstraintList::~PropertyConstraintList()
{
for (std::vector<Constraint*>::iterator it = _lValueList.begin(); it != _lValueList.end(); ++it)
if (*it) delete *it;
if (*it)
delete *it;
}
App::ObjectIdentifier PropertyConstraintList::makeArrayPath(int idx)
{
return App::ObjectIdentifier(*this,idx);
return App::ObjectIdentifier(*this, idx);
}
App::ObjectIdentifier PropertyConstraintList::makeSimplePath(const Constraint * c)
App::ObjectIdentifier PropertyConstraintList::makeSimplePath(const Constraint* c)
{
return App::ObjectIdentifier(*this) << App::ObjectIdentifier::SimpleComponent(
App::ObjectIdentifier::String(c->Name, !ExpressionParser::isTokenAnIndentifier(c->Name)));
return App::ObjectIdentifier(*this)
<< App::ObjectIdentifier::SimpleComponent(App::ObjectIdentifier::String(
c->Name, !ExpressionParser::isTokenAnIndentifier(c->Name)));
}
App::ObjectIdentifier PropertyConstraintList::makePath(int idx, const Constraint * c)
App::ObjectIdentifier PropertyConstraintList::makePath(int idx, const Constraint* c)
{
return c->Name.empty() ? makeArrayPath(idx) : makeSimplePath(c);
}
@@ -176,13 +176,14 @@ void PropertyConstraintList::setValue(const Constraint* lValue)
void PropertyConstraintList::setValues(const std::vector<Constraint*>& lValue)
{
auto copy = lValue;
for(auto &cstr : copy)
for (auto& cstr : copy)
cstr = cstr->clone();
setValues(std::move(copy));
}
void PropertyConstraintList::setValues(std::vector<Constraint*>&& lValue) {
void PropertyConstraintList::setValues(std::vector<Constraint*>&& lValue)
{
aboutToSetValue();
applyValues(std::move(lValue));
hasSetValue();
@@ -190,18 +191,19 @@ void PropertyConstraintList::setValues(std::vector<Constraint*>&& lValue) {
void PropertyConstraintList::applyValues(std::vector<Constraint*>&& lValue)
{
std::set<Constraint*> oldVals(_lValueList.begin(),_lValueList.end());
std::set<Constraint*> oldVals(_lValueList.begin(), _lValueList.end());
std::map<App::ObjectIdentifier, App::ObjectIdentifier> renamed;
std::set<App::ObjectIdentifier> removed;
boost::unordered_map<boost::uuids::uuid, std::size_t> newValueMap;
/* Check for renames */
for (unsigned int i = 0; i < lValue.size(); i++) {
boost::unordered_map<boost::uuids::uuid, std::size_t>::const_iterator j = valueMap.find(lValue[i]->tag);
boost::unordered_map<boost::uuids::uuid, std::size_t>::const_iterator j =
valueMap.find(lValue[i]->tag);
if (j != valueMap.end()) {
if(i != j->second || _lValueList[j->second]->Name != lValue[i]->Name) {
App::ObjectIdentifier old_oid(makePath(j->second, _lValueList[j->second] ));
if (i != j->second || _lValueList[j->second]->Name != lValue[i]->Name) {
App::ObjectIdentifier old_oid(makePath(j->second, _lValueList[j->second]));
App::ObjectIdentifier new_oid(makePath(i, lValue[i]));
renamed[old_oid] = new_oid;
}
@@ -215,13 +217,14 @@ void PropertyConstraintList::applyValues(std::vector<Constraint*>&& lValue)
}
/* Collect info about removed elements */
for(auto &v : valueMap)
removed.insert(makePath(v.second,_lValueList[v.second]));
for (auto& v : valueMap)
removed.insert(makePath(v.second, _lValueList[v.second]));
/* Update value map with new tags from new array */
valueMap = std::move(newValueMap);
/* Signal removes first, in case renamed values below have the same names as some of the removed ones. */
/* Signal removes first, in case renamed values below have the same names as some of the removed
* ones. */
if (!removed.empty() && !restoreFromTransaction)
signalConstraintsRemoved(removed);
@@ -232,52 +235,54 @@ void PropertyConstraintList::applyValues(std::vector<Constraint*>&& lValue)
_lValueList = std::move(lValue);
/* Clean-up; remove old values */
for(auto &v : oldVals)
for (auto& v : oldVals)
delete v;
}
PyObject *PropertyConstraintList::getPyObject()
PyObject* PropertyConstraintList::getPyObject()
{
PyObject* list = PyList_New(getSize());
for (int i = 0; i < getSize(); i++)
PyList_SetItem( list, i, _lValueList[i]->getPyObject());
PyList_SetItem(list, i, _lValueList[i]->getPyObject());
return list;
}
bool PropertyConstraintList::getPyPathValue(const App::ObjectIdentifier &path, Py::Object &res) const {
if(path.numSubComponents()!=2 || path.getPropertyComponent(0).getName()!=getName())
bool PropertyConstraintList::getPyPathValue(const App::ObjectIdentifier& path,
Py::Object& res) const
{
if (path.numSubComponents() != 2 || path.getPropertyComponent(0).getName() != getName())
return false;
const ObjectIdentifier::Component & c1 = path.getPropertyComponent(1);
const ObjectIdentifier::Component& c1 = path.getPropertyComponent(1);
const Constraint *cstr = nullptr;
const Constraint* cstr = nullptr;
if (c1.isArray())
cstr = _lValueList[c1.getIndex(_lValueList.size())];
else if (c1.isSimple()) {
ObjectIdentifier::Component c1 = path.getPropertyComponent(1);
for(auto c : _lValueList) {
if(c->Name == c1.getName()) {
for (auto c : _lValueList) {
if (c->Name == c1.getName()) {
cstr = c;
break;
}
}
}
if(!cstr)
if (!cstr)
return false;
Quantity q = cstr->getPresentationValue();
res = new Base::QuantityPy(new Base::Quantity(q));
return true;
}
void PropertyConstraintList::setPyObject(PyObject *value)
void PropertyConstraintList::setPyObject(PyObject* value)
{
if (PyList_Check(value)) {
Py_ssize_t nSize = PyList_Size(value);
std::vector<Constraint*> values;
values.resize(nSize);
for (Py_ssize_t i=0; i < nSize; ++i) {
for (Py_ssize_t i = 0; i < nSize; ++i) {
PyObject* item = PyList_GetItem(value, i);
if (!PyObject_TypeCheck(item, &(ConstraintPy::Type))) {
std::string error = std::string("types in list must be 'Constraint', not ");
@@ -291,7 +296,7 @@ void PropertyConstraintList::setPyObject(PyObject *value)
setValues(values);
}
else if (PyObject_TypeCheck(value, &(ConstraintPy::Type))) {
ConstraintPy *pcObject = static_cast<ConstraintPy*>(value);
ConstraintPy* pcObject = static_cast<ConstraintPy*>(value);
setValue(pcObject->getConstraintPtr());
}
else {
@@ -301,17 +306,17 @@ void PropertyConstraintList::setPyObject(PyObject *value)
}
}
void PropertyConstraintList::Save(Writer &writer) const
void PropertyConstraintList::Save(Writer& writer) const
{
writer.Stream() << writer.ind() << "<ConstraintList count=\"" << getSize() <<"\">" << endl;
writer.Stream() << writer.ind() << "<ConstraintList count=\"" << getSize() << "\">" << endl;
writer.incInd();
for (int i = 0; i < getSize(); i++)
_lValueList[i]->Save(writer);
writer.decInd();
writer.Stream() << writer.ind() << "</ConstraintList>" << endl ;
writer.Stream() << writer.ind() << "</ConstraintList>" << endl;
}
void PropertyConstraintList::Restore(Base::XMLReader &reader)
void PropertyConstraintList::Restore(Base::XMLReader& reader)
{
// read my element
reader.readElement("ConstraintList");
@@ -321,7 +326,7 @@ void PropertyConstraintList::Restore(Base::XMLReader &reader)
std::vector<Constraint*> values;
values.reserve(count);
for (int i = 0; i < count; i++) {
Constraint *newC = new Constraint();
Constraint* newC = new Constraint();
newC->Restore(reader);
// To keep upward compatibility ignore unknown constraint types
if (newC->Type < Sketcher::NumConstraintTypes) {
@@ -339,15 +344,15 @@ void PropertyConstraintList::Restore(Base::XMLReader &reader)
setValues(std::move(values));
}
Property *PropertyConstraintList::Copy() const
Property* PropertyConstraintList::Copy() const
{
PropertyConstraintList *p = new PropertyConstraintList();
PropertyConstraintList* p = new PropertyConstraintList();
p->applyValidGeometryKeys(validGeometryKeys);
p->setValues(_lValueList);
return p;
}
void PropertyConstraintList::Paste(const Property &from)
void PropertyConstraintList::Paste(const Property& from)
{
Base::StateLocker lock(restoreFromTransaction, true);
const PropertyConstraintList& FromList = dynamic_cast<const PropertyConstraintList&>(from);
@@ -362,7 +367,7 @@ unsigned int PropertyConstraintList::getMemSize() const
return size;
}
void PropertyConstraintList::acceptGeometry(const std::vector<Part::Geometry *> &GeoList)
void PropertyConstraintList::acceptGeometry(const std::vector<Part::Geometry*>& GeoList)
{
aboutToSetValue();
validGeometryKeys.clear();
@@ -373,21 +378,21 @@ void PropertyConstraintList::acceptGeometry(const std::vector<Part::Geometry *>
hasSetValue();
}
void PropertyConstraintList::applyValidGeometryKeys(const std::vector<unsigned int> &keys)
void PropertyConstraintList::applyValidGeometryKeys(const std::vector<unsigned int>& keys)
{
validGeometryKeys = keys;
}
bool PropertyConstraintList::checkGeometry(const std::vector<Part::Geometry *> &GeoList)
bool PropertyConstraintList::checkGeometry(const std::vector<Part::Geometry*>& GeoList)
{
if (!scanGeometry(GeoList)) {
invalidGeometry = true;
return invalidGeometry;
}
//if we made it here, geometry is OK
// if we made it here, geometry is OK
if (invalidGeometry) {
//geometry was bad, but now it became OK.
// geometry was bad, but now it became OK.
invalidGeometry = false;
touch();
}
@@ -400,18 +405,18 @@ bool PropertyConstraintList::checkConstraintIndices(int geomax, int geomin)
int mininternalgeoid = std::numeric_limits<int>::max();
int maxinternalgeoid = GeoEnum::GeoUndef;
auto cmin = [] (int previousmin, int cindex) {
if( cindex == GeoEnum::GeoUndef )
auto cmin = [](int previousmin, int cindex) {
if (cindex == GeoEnum::GeoUndef)
return previousmin;
return ( cindex < previousmin )? cindex : previousmin;
return (cindex < previousmin) ? cindex : previousmin;
};
auto cmax = [] (int previousmax, int cindex) {
return ( cindex > previousmax )? cindex : previousmax;
auto cmax = [](int previousmax, int cindex) {
return (cindex > previousmax) ? cindex : previousmax;
};
for (const auto &v : _lValueList) {
for (const auto& v : _lValueList) {
mininternalgeoid = cmin(mininternalgeoid, v->First);
mininternalgeoid = cmin(mininternalgeoid, v->Second);
@@ -422,7 +427,7 @@ bool PropertyConstraintList::checkConstraintIndices(int geomax, int geomin)
maxinternalgeoid = cmax(maxinternalgeoid, v->Third);
}
if(maxinternalgeoid > geomax || mininternalgeoid < geomin)
if (maxinternalgeoid > geomax || mininternalgeoid < geomin)
invalidIndices = true;
else
invalidIndices = false;
@@ -436,15 +441,15 @@ bool PropertyConstraintList::checkConstraintIndices(int geomax, int geomin)
* \param GeoList - new geometry list to be checked
* \return false, if the types have changed.
*/
bool PropertyConstraintList::scanGeometry(const std::vector<Part::Geometry *> &GeoList) const
bool PropertyConstraintList::scanGeometry(const std::vector<Part::Geometry*>& GeoList) const
{
if (validGeometryKeys.size() != GeoList.size()) {
return false;
}
unsigned int i=0;
for (std::vector< Part::Geometry * >::const_iterator it=GeoList.begin();
it != GeoList.end(); ++it, i++) {
unsigned int i = 0;
for (std::vector<Part::Geometry*>::const_iterator it = GeoList.begin(); it != GeoList.end();
++it, i++) {
if (validGeometryKeys[i] != (*it)->getTypeId().getKey()) {
return false;
}
@@ -453,7 +458,7 @@ bool PropertyConstraintList::scanGeometry(const std::vector<Part::Geometry *> &G
return true;
}
string PropertyConstraintList::getConstraintName(const std::string & name, int i)
string PropertyConstraintList::getConstraintName(const std::string& name, int i)
{
if (!name.empty())
return name;
@@ -469,27 +474,27 @@ string PropertyConstraintList::getConstraintName(int i)
return str.str();
}
bool PropertyConstraintList::validConstraintName(const std::string & name)
bool PropertyConstraintList::validConstraintName(const std::string& name)
{
return !name.empty();
}
ObjectIdentifier PropertyConstraintList::createPath(int ConstrNbr) const
{
return App::ObjectIdentifier(*this,ConstrNbr);
return App::ObjectIdentifier(*this, ConstrNbr);
}
int PropertyConstraintList::getIndexFromConstraintName(const string &name)
int PropertyConstraintList::getIndexFromConstraintName(const string& name)
{
return std::atoi(name.substr(10,4000).c_str()) - 1;
return std::atoi(name.substr(10, 4000).c_str()) - 1;
}
void PropertyConstraintList::setPathValue(const ObjectIdentifier &path, const boost::any &value)
void PropertyConstraintList::setPathValue(const ObjectIdentifier& path, const boost::any& value)
{
if(path.numSubComponents()!=2 || path.getPropertyComponent(0).getName()!=getName())
FC_THROWM(Base::ValueError,"invalid constraint path " << path.toString());
if (path.numSubComponents() != 2 || path.getPropertyComponent(0).getName() != getName())
FC_THROWM(Base::ValueError, "invalid constraint path " << path.toString());
const ObjectIdentifier::Component & c1 = path.getPropertyComponent(1);
const ObjectIdentifier::Component& c1 = path.getPropertyComponent(1);
double dvalue;
if (value.type() == typeid(double))
@@ -501,18 +506,18 @@ void PropertyConstraintList::setPathValue(const ObjectIdentifier &path, const bo
else if (value.type() == typeid(int))
dvalue = App::any_cast<int>(value);
else if (value.type() == typeid(Quantity))
dvalue = (App::any_cast<const Quantity &>(value)).getValue();
dvalue = (App::any_cast<const Quantity&>(value)).getValue();
else
throw std::bad_cast();
if (c1.isArray()) {
size_t index = c1.getIndex(_lValueList.size());
switch (_lValueList[index]->Type) {
case Angle:
dvalue = Base::toRadians<double>(dvalue);
break;
default:
break;
case Angle:
dvalue = Base::toRadians<double>(dvalue);
break;
default:
break;
}
aboutToSetValue();
_lValueList[index]->setValue(dvalue);
@@ -520,16 +525,18 @@ void PropertyConstraintList::setPathValue(const ObjectIdentifier &path, const bo
return;
}
else if (c1.isSimple()) {
for (std::vector<Constraint *>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
for (std::vector<Constraint*>::const_iterator it = _lValueList.begin();
it != _lValueList.end();
++it) {
int index = it - _lValueList.begin();
if ((*it)->Name == c1.getName()) {
switch (_lValueList[index]->Type) {
case Angle:
dvalue = Base::toRadians<double>(dvalue);
break;
default:
break;
case Angle:
dvalue = Base::toRadians<double>(dvalue);
break;
default:
break;
}
aboutToSetValue();
_lValueList[index]->setValue(dvalue);
@@ -538,15 +545,15 @@ void PropertyConstraintList::setPathValue(const ObjectIdentifier &path, const bo
}
}
}
FC_THROWM(Base::ValueError,"invalid constraint path " << path.toString());
FC_THROWM(Base::ValueError, "invalid constraint path " << path.toString());
}
const Constraint * PropertyConstraintList::getConstraint(const ObjectIdentifier &path) const
const Constraint* PropertyConstraintList::getConstraint(const ObjectIdentifier& path) const
{
if(path.numSubComponents()!=2 || path.getPropertyComponent(0).getName()!=getName())
FC_THROWM(Base::ValueError,"Invalid constraint path " << path.toString());
if (path.numSubComponents() != 2 || path.getPropertyComponent(0).getName() != getName())
FC_THROWM(Base::ValueError, "Invalid constraint path " << path.toString());
const ObjectIdentifier::Component & c1 = path.getPropertyComponent(1);
const ObjectIdentifier::Component& c1 = path.getPropertyComponent(1);
if (c1.isArray()) {
return _lValueList[c1.getIndex(_lValueList.size())];
@@ -554,44 +561,49 @@ const Constraint * PropertyConstraintList::getConstraint(const ObjectIdentifier
else if (c1.isSimple()) {
ObjectIdentifier::Component c1 = path.getPropertyComponent(1);
for (std::vector<Constraint *>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
for (std::vector<Constraint*>::const_iterator it = _lValueList.begin();
it != _lValueList.end();
++it) {
if ((*it)->Name == c1.getName())
return *it;
}
}
FC_THROWM(Base::ValueError,"Invalid constraint path " << path.toString());
FC_THROWM(Base::ValueError, "Invalid constraint path " << path.toString());
}
const boost::any PropertyConstraintList::getPathValue(const ObjectIdentifier &path) const
const boost::any PropertyConstraintList::getPathValue(const ObjectIdentifier& path) const
{
return boost::any(getConstraint(path)->getPresentationValue());
}
ObjectIdentifier PropertyConstraintList::canonicalPath(const ObjectIdentifier &p) const
ObjectIdentifier PropertyConstraintList::canonicalPath(const ObjectIdentifier& p) const
{
if(p.numSubComponents()!=2 || p.getPropertyComponent(0).getName()!=getName())
FC_THROWM(Base::ValueError,"Invalid constraint path " << p.toString());
if (p.numSubComponents() != 2 || p.getPropertyComponent(0).getName() != getName())
FC_THROWM(Base::ValueError, "Invalid constraint path " << p.toString());
const ObjectIdentifier::Component & c1 = p.getPropertyComponent(1);
const ObjectIdentifier::Component& c1 = p.getPropertyComponent(1);
if (c1.isArray()) {
size_t idx = c1.getIndex();
if (idx < _lValueList.size() && !_lValueList[idx]->Name.empty())
return ObjectIdentifier(*this) << ObjectIdentifier::SimpleComponent(_lValueList[idx]->Name);
return ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(_lValueList[idx]->Name);
return p;
}
else if (c1.isSimple()) {
return p;
}
FC_THROWM(Base::ValueError,"Invalid constraint path " << p.toString());
FC_THROWM(Base::ValueError, "Invalid constraint path " << p.toString());
}
void PropertyConstraintList::getPaths(std::vector<ObjectIdentifier> &paths) const
void PropertyConstraintList::getPaths(std::vector<ObjectIdentifier>& paths) const
{
for (std::vector<Constraint *>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
for (std::vector<Constraint*>::const_iterator it = _lValueList.begin(); it != _lValueList.end();
++it) {
if (!(*it)->Name.empty())
paths.push_back(ObjectIdentifier(*this) << ObjectIdentifier::SimpleComponent((*it)->Name));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent((*it)->Name));
}
}
std::vector<Constraint *> PropertyConstraintList::_emptyValueList(0);
std::vector<Constraint*> PropertyConstraintList::_emptyValueList(0);

View File

@@ -26,8 +26,8 @@
#include <string>
#include <vector>
#include <boost_signals2.hpp>
#include <boost/unordered/unordered_map.hpp>
#include <boost_signals2.hpp>
#include <App/Property.h>
#include <Mod/Part/App/Geometry.h>
@@ -35,7 +35,8 @@
#include "Constraint.h"
namespace Base {
namespace Base
{
class Writer;
}
@@ -43,7 +44,7 @@ namespace Sketcher
{
class Constraint;
class SketcherExport PropertyConstraintList : public App::PropertyLists
class SketcherExport PropertyConstraintList: public App::PropertyLists
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -63,7 +64,8 @@ public:
void setSize(int newSize) override;
int getSize() const override;
const char* getEditorName() const override {
const char* getEditorName() const override
{
return "SketcherGui::PropertyConstraintListItem";
}
@@ -98,67 +100,76 @@ public:
\note If the geometry is invalid then the index operator
returns null. This must be checked by the caller.
*/
const Constraint *operator[] (const int idx) const {
const Constraint* operator[](const int idx) const
{
return (invalidGeometry || invalidIndices) ? nullptr : _lValueList[idx];
}
const std::vector<Constraint*> &getValues() const {
const std::vector<Constraint*>& getValues() const
{
return (invalidGeometry || invalidIndices) ? _emptyValueList : _lValueList;
}
const std::vector<Constraint*> &getValuesForce() const {//to suppress check for invalid geometry, to be used for sketch repairing.
return _lValueList;
// to suppress check for invalid geometry, to be used for sketch repairing.
const std::vector<Constraint*>& getValuesForce() const
{
return _lValueList;
}
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
PyObject* getPyObject() override;
void setPyObject(PyObject*) override;
void Save(Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
void Save(Base::Writer& writer) const override;
void Restore(Base::XMLReader& reader) override;
Property *Copy() const override;
void Paste(const App::Property &from) override;
Property* Copy() const override;
void Paste(const App::Property& from) override;
unsigned int getMemSize() const override;
void acceptGeometry(const std::vector<Part::Geometry *> &GeoList);
bool checkGeometry(const std::vector<Part::Geometry *> &GeoList);
bool scanGeometry(const std::vector<Part::Geometry *> &GeoList) const;
void acceptGeometry(const std::vector<Part::Geometry*>& GeoList);
bool checkGeometry(const std::vector<Part::Geometry*>& GeoList);
bool scanGeometry(const std::vector<Part::Geometry*>& GeoList) const;
bool checkConstraintIndices(int geomax, int geomin);
/// Return status of geometry for better error reporting
bool hasInvalidGeometry() const { return invalidGeometry; }
bool hasInvalidGeometry() const
{
return invalidGeometry;
}
const Constraint *getConstraint(const App::ObjectIdentifier &path) const;
void setPathValue(const App::ObjectIdentifier & path, const boost::any & value) override;
const boost::any getPathValue(const App::ObjectIdentifier & path) const override;
App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier & p) const override;
void getPaths(std::vector<App::ObjectIdentifier> & paths) const override;
const Constraint* getConstraint(const App::ObjectIdentifier& path) const;
void setPathValue(const App::ObjectIdentifier& path, const boost::any& value) override;
const boost::any getPathValue(const App::ObjectIdentifier& path) const override;
App::ObjectIdentifier canonicalPath(const App::ObjectIdentifier& p) const override;
void getPaths(std::vector<App::ObjectIdentifier>& paths) const override;
bool getPyPathValue(const App::ObjectIdentifier &path, Py::Object &res) const override;
bool getPyPathValue(const App::ObjectIdentifier& path, Py::Object& res) const override;
using ConstraintInfo = std::pair<int, const Constraint*> ;
using ConstraintInfo = std::pair<int, const Constraint*>;
boost::signals2::signal<void (const std::map<App::ObjectIdentifier, App::ObjectIdentifier> &)> signalConstraintsRenamed;
boost::signals2::signal<void (const std::set<App::ObjectIdentifier> &)> signalConstraintsRemoved;
boost::signals2::signal<void(const std::map<App::ObjectIdentifier, App::ObjectIdentifier>&)>
signalConstraintsRenamed;
boost::signals2::signal<void(const std::set<App::ObjectIdentifier>&)> signalConstraintsRemoved;
static std::string getConstraintName(const std::string &name, int i);
static std::string getConstraintName(const std::string& name, int i);
static std::string getConstraintName(int i);
static int getIndexFromConstraintName(const std::string & name);
static int getIndexFromConstraintName(const std::string& name);
static bool validConstraintName(const std::string &name);
static bool validConstraintName(const std::string& name);
App::ObjectIdentifier createPath(int ConstrNbr) const;
private:
App::ObjectIdentifier makeArrayPath(int idx);
App::ObjectIdentifier makeSimplePath(const Constraint *c);
App::ObjectIdentifier makePath(int idx, const Constraint *c);
App::ObjectIdentifier makeSimplePath(const Constraint* c);
App::ObjectIdentifier makePath(int idx, const Constraint* c);
std::vector<Constraint *> _lValueList;
std::vector<Constraint*> _lValueList;
boost::unordered_map<boost::uuids::uuid, std::size_t> valueMap;
std::vector<unsigned int> validGeometryKeys;
@@ -167,12 +178,12 @@ private:
bool invalidIndices;
void applyValues(std::vector<Constraint*>&&);
void applyValidGeometryKeys(const std::vector<unsigned int> &keys);
void applyValidGeometryKeys(const std::vector<unsigned int>& keys);
static std::vector<Constraint *> _emptyValueList;
static std::vector<Constraint*> _emptyValueList;
};
} // namespace Sketcher
}// namespace Sketcher
#endif // APP_PropertyConstraintList_H
#endif// APP_PropertyConstraintList_H

View File

@@ -22,8 +22,8 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <boost/format.hpp>
#endif // #ifndef _PreComp_
#include <boost/format.hpp>
#endif// #ifndef _PreComp_
#include <Base/Exception.h>
#include <Mod/Sketcher/App/Constraint.h>
@@ -34,20 +34,20 @@
using namespace Sketcher;
std::string PythonConverter::convert(const Part::Geometry * geo)
std::string PythonConverter::convert(const Part::Geometry* geo)
{
// "addGeometry(Part.LineSegment(App.Vector(%f,%f,0),App.Vector(%f,%f,0)),%s)"
std::string command;
auto sg = process(geo);
command = boost::str(boost::format("addGeometry(%s,%s)\n") %
sg.creation % (sg.construction ? "True":"False"));
command = boost::str(boost::format("addGeometry(%s,%s)\n") % sg.creation
% (sg.construction ? "True" : "False"));
return command;
}
std::string PythonConverter::convert(const Sketcher::Constraint * constraint)
std::string PythonConverter::convert(const Sketcher::Constraint* constraint)
{
// addConstraint(Sketcher.Constraint('Distance',%d,%f))
std::string command;
@@ -58,41 +58,42 @@ std::string PythonConverter::convert(const Sketcher::Constraint * constraint)
return command;
}
std::string PythonConverter::convert(const std::string & doc, const std::vector<Part::Geometry *> & geos)
std::string PythonConverter::convert(const std::string& doc,
const std::vector<Part::Geometry*>& geos)
{
std::string geolist = "geoList = []\n";
std::string constrgeolist = "constrGeoList = []\n";
int ngeo = 0, nconstr = 0;
for(auto geo : geos) {
for (auto geo : geos) {
auto sg = process(geo);
if (sg.construction) {
constrgeolist = boost::str(boost::format("%s\nconstrGeoList.append(%s)\n") %
constrgeolist % sg.creation);
constrgeolist = boost::str(boost::format("%s\nconstrGeoList.append(%s)\n")
% constrgeolist % sg.creation);
nconstr++;
}
else {
geolist = boost::str(boost::format("%s\ngeoList.append(%s)\n") %
geolist % sg.creation);
geolist = boost::str(boost::format("%s\ngeoList.append(%s)\n") % geolist % sg.creation);
ngeo++;
}
}
if(ngeo > 0) {
geolist = boost::str(boost::format("%s\n%s.addGeometry(geoList,%s)\ndel geoList\n") %
geolist % doc % "False");
if (ngeo > 0) {
geolist = boost::str(boost::format("%s\n%s.addGeometry(geoList,%s)\ndel geoList\n")
% geolist % doc % "False");
}
if(nconstr > 0) {
constrgeolist = boost::str(boost::format("%s\n%s.addGeometry(constrGeoList,%s)\ndel constrGeoList") %
constrgeolist % doc % "True");
if (nconstr > 0) {
constrgeolist =
boost::str(boost::format("%s\n%s.addGeometry(constrGeoList,%s)\ndel constrGeoList")
% constrgeolist % doc % "True");
}
std::string command;
if(ngeo > 0 && nconstr > 0)
if (ngeo > 0 && nconstr > 0)
command = geolist + constrgeolist;
else if (ngeo > 0)
command = std::move(geolist);
@@ -102,95 +103,107 @@ std::string PythonConverter::convert(const std::string & doc, const std::vector<
return command;
}
std::string PythonConverter::convert(const std::string & doc, const std::vector<Sketcher::Constraint *> & constraints)
std::string PythonConverter::convert(const std::string& doc,
const std::vector<Sketcher::Constraint*>& constraints)
{
if(constraints.size() == 1) {
if (constraints.size() == 1) {
auto cg = convert(constraints[0]);
return boost::str(boost::format("%s.%s\n") %
doc % cg);
return boost::str(boost::format("%s.%s\n") % doc % cg);
}
std::string constraintlist = "constraintList = []";
for(auto constraint : constraints) {
for (auto constraint : constraints) {
auto cg = process(constraint);
constraintlist = boost::str(boost::format("%s\nconstraintList.append(%s)") %
constraintlist % cg);
constraintlist =
boost::str(boost::format("%s\nconstraintList.append(%s)") % constraintlist % cg);
}
if(!constraints.empty()) {
constraintlist = boost::str(boost::format("%s\n%s.addConstraint(constraintList)\ndel constraintList\n") %
constraintlist % doc);
if (!constraints.empty()) {
constraintlist =
boost::str(boost::format("%s\n%s.addConstraint(constraintList)\ndel constraintList\n")
% constraintlist % doc);
}
return constraintlist;
}
PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry * geo)
PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* geo)
{
static std::map<const Base::Type, std::function<SingleGeometry(const Part::Geometry * geo)>> converterMap = {
{ Part::GeomLineSegment::getClassTypeId(),
[](const Part::Geometry * geo){
auto sgeo = static_cast<const Part::GeomLineSegment *>(geo);
SingleGeometry sg;
sg.creation = boost::str(boost::format("Part.LineSegment(App.Vector(%f,%f,%f),App.Vector(%f,%f,%f))") %
sgeo->getStartPoint().x % sgeo->getStartPoint().y % sgeo->getStartPoint().z %
sgeo->getEndPoint().x % sgeo->getEndPoint().y % sgeo->getEndPoint().z);
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{ Part::GeomArcOfCircle::getClassTypeId(),
[](const Part::Geometry * geo){
auto arc = static_cast<const Part::GeomArcOfCircle *>(geo);
SingleGeometry sg;
sg.creation = boost::str(boost::format("Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, %f), App.Vector(%f, %f, %f), %f), %f, %f)") %
arc->getCenter().x % arc->getCenter().y % arc->getCenter().z %
arc->getAxisDirection().x % arc->getAxisDirection().y % arc->getAxisDirection().z %
arc->getRadius() % arc->getFirstParameter() % arc->getLastParameter());
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{ Part::GeomPoint::getClassTypeId(),
[](const Part::Geometry* geo) {
auto sgeo = static_cast<const Part::GeomPoint*>(geo);
SingleGeometry sg;
sg.creation = boost::str(boost::format("Part.Point(App.Vector(%f,%f,%f))") %
sgeo->getPoint().x % sgeo->getPoint().y % sgeo->getPoint().z);
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{ Part::GeomEllipse::getClassTypeId(),
[](const Part::Geometry * geo){
auto ellipse = static_cast<const Part::GeomEllipse *>(geo);
SingleGeometry sg;
auto periapsis = ellipse->getCenter() + ellipse->getMajorAxisDir() * ellipse->getMajorRadius();
auto positiveB = ellipse->getCenter() + ellipse->getMinorAxisDir() * ellipse->getMinorRadius();
auto center = ellipse->getCenter();
sg.creation = boost::str(boost::format("Part.Ellipse(App.Vector(%f, %f, %f), App.Vector(%f, %f, %f), App.Vector(%f, %f, %f))") %
periapsis.x % periapsis.y % periapsis.z %
positiveB.x % positiveB.y % positiveB.z %
center.x % center.y % center.z);
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{ Part::GeomCircle::getClassTypeId(),
[](const Part::Geometry * geo){
auto circle = static_cast<const Part::GeomCircle *>(geo);
SingleGeometry sg;
sg.creation = boost::str(boost::format("Part.Circle(App.Vector(%f, %f, %f), App.Vector(%f, %f, %f), %f)") %
circle->getCenter().x % circle->getCenter().y % circle->getCenter().z %
circle->getAxisDirection().x % circle->getAxisDirection().y % circle->getAxisDirection().z %
circle->getRadius());
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
};
static std::map<const Base::Type, std::function<SingleGeometry(const Part::Geometry* geo)>>
converterMap = {
{Part::GeomLineSegment::getClassTypeId(),
[](const Part::Geometry* geo) {
auto sgeo = static_cast<const Part::GeomLineSegment*>(geo);
SingleGeometry sg;
sg.creation = boost::str(
boost::format("Part.LineSegment(App.Vector(%f,%f,%f),App.Vector(%f,%f,%f))")
% sgeo->getStartPoint().x % sgeo->getStartPoint().y % sgeo->getStartPoint().z
% sgeo->getEndPoint().x % sgeo->getEndPoint().y % sgeo->getEndPoint().z);
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomArcOfCircle::getClassTypeId(),
[](const Part::Geometry* geo) {
auto arc = static_cast<const Part::GeomArcOfCircle*>(geo);
SingleGeometry sg;
sg.creation =
boost::str(boost::format("Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, "
"%f), App.Vector(%f, %f, %f), %f), %f, %f)")
% arc->getCenter().x % arc->getCenter().y % arc->getCenter().z
% arc->getAxisDirection().x % arc->getAxisDirection().y
% arc->getAxisDirection().z % arc->getRadius()
% arc->getFirstParameter() % arc->getLastParameter());
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomPoint::getClassTypeId(),
[](const Part::Geometry* geo) {
auto sgeo = static_cast<const Part::GeomPoint*>(geo);
SingleGeometry sg;
sg.creation =
boost::str(boost::format("Part.Point(App.Vector(%f,%f,%f))")
% sgeo->getPoint().x % sgeo->getPoint().y % sgeo->getPoint().z);
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomEllipse::getClassTypeId(),
[](const Part::Geometry* geo) {
auto ellipse = static_cast<const Part::GeomEllipse*>(geo);
SingleGeometry sg;
auto periapsis =
ellipse->getCenter() + ellipse->getMajorAxisDir() * ellipse->getMajorRadius();
auto positiveB =
ellipse->getCenter() + ellipse->getMinorAxisDir() * ellipse->getMinorRadius();
auto center = ellipse->getCenter();
sg.creation =
boost::str(boost::format("Part.Ellipse(App.Vector(%f, %f, %f), App.Vector(%f, "
"%f, %f), App.Vector(%f, %f, %f))")
% periapsis.x % periapsis.y % periapsis.z % positiveB.x
% positiveB.y % positiveB.z % center.x % center.y % center.z);
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomCircle::getClassTypeId(),
[](const Part::Geometry* geo) {
auto circle = static_cast<const Part::GeomCircle*>(geo);
SingleGeometry sg;
sg.creation = boost::str(
boost::format(
"Part.Circle(App.Vector(%f, %f, %f), App.Vector(%f, %f, %f), %f)")
% circle->getCenter().x % circle->getCenter().y % circle->getCenter().z
% circle->getAxisDirection().x % circle->getAxisDirection().y
% circle->getAxisDirection().z % circle->getRadius());
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
};
auto result = converterMap.find(geo->getTypeId());
if( result == converterMap.end())
if (result == converterMap.end())
THROWM(Base::ValueError, "PythonConverter: Geometry Type not supported")
auto creator = result->second;
@@ -198,210 +211,248 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry *
return creator(geo);
}
std::string PythonConverter::process(const Sketcher::Constraint * constraint)
std::string PythonConverter::process(const Sketcher::Constraint* constraint)
{
static std::map<const Sketcher::ConstraintType, std::function<std::string(const Sketcher::Constraint *)>> converterMap = {
{ Sketcher::Coincident,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('Coincident', %i, %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % static_cast<int>(constr->SecondPos));
}},
{ Sketcher::Horizontal,
[](const Sketcher::Constraint * constr){
if(constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('Horizontal', %i)") % constr->First);
}
else {
return boost::str(boost::format("Sketcher.Constraint('Horizontal', %i, %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % static_cast<int>(constr->SecondPos));
}
}},
{ Sketcher::Vertical,
[](const Sketcher::Constraint * constr){
if(constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('Vertical', %i)") % constr->First);
}
else {
return boost::str(boost::format("Sketcher.Constraint('Vertical', %i, %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % static_cast<int>(constr->SecondPos));
}
}},
{ Sketcher::Block,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('Block', %i)") % constr->First);
}},
{ Sketcher::Tangent,
[](const Sketcher::Constraint * constr){
if(constr->FirstPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i)") %
constr->First % constr->Second);
}
else if(constr->SecondPos == Sketcher::PointPos::none){
return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second);
}
else {
return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % static_cast<int>(constr->SecondPos));
}
}},
{ Sketcher::Parallel,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('Parallel', %i, %i)") %
constr->First % constr->Second);
}},
{ Sketcher::Perpendicular,
[](const Sketcher::Constraint * constr){
if(constr->FirstPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %i, %i)") %
constr->First % constr->Second);
}
else if(constr->SecondPos == Sketcher::PointPos::none){
return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second);
}
else {
return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %i, %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % static_cast<int>(constr->SecondPos));
}
}},
{ Sketcher::Equal,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('Equal', %i, %i)") %
constr->First % constr->Second);
}},
{ Sketcher::InternalAlignment,
[](const Sketcher::Constraint * constr){
if(constr->InternalAlignmentIndex == EllipseMajorDiameter ||
constr->InternalAlignmentIndex == EllipseMinorDiameter) {
return boost::str(boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i)") %
constr->internalAlignmentTypeToString() % constr->First % constr->Second);
}
else if(constr->InternalAlignmentIndex == EllipseFocus1 ||
constr->InternalAlignmentIndex == EllipseFocus2) {
return boost::str(boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i)") %
constr->internalAlignmentTypeToString() % constr->First % static_cast<int>(constr->FirstPos) % constr->Second);
}
else if(constr->InternalAlignmentIndex == BSplineControlPoint) {
return boost::str(boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i, %i)") %
constr->internalAlignmentTypeToString() % constr->First % static_cast<int>(constr->FirstPos) %
constr->Second % constr->InternalAlignmentIndex);
}
static std::map<const Sketcher::ConstraintType,
std::function<std::string(const Sketcher::Constraint*)>>
converterMap = {
{Sketcher::Coincident,
[](const Sketcher::Constraint* constr) {
return boost::str(
boost::format("Sketcher.Constraint('Coincident', %i, %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos));
}},
{Sketcher::Horizontal,
[](const Sketcher::Constraint* constr) {
if (constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('Horizontal', %i)")
% constr->First);
}
else {
return boost::str(
boost::format("Sketcher.Constraint('Horizontal', %i, %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos));
}
}},
{Sketcher::Vertical,
[](const Sketcher::Constraint* constr) {
if (constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('Vertical', %i)")
% constr->First);
}
else {
return boost::str(
boost::format("Sketcher.Constraint('Vertical', %i, %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos));
}
}},
{Sketcher::Block,
[](const Sketcher::Constraint* constr) {
return boost::str(boost::format("Sketcher.Constraint('Block', %i)")
% constr->First);
}},
{Sketcher::Tangent,
[](const Sketcher::Constraint* constr) {
if (constr->FirstPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i)")
% constr->First % constr->Second);
}
else if (constr->SecondPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos)
% constr->Second);
}
else {
return boost::str(
boost::format("Sketcher.Constraint('Tangent', %i, %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos));
}
}},
{Sketcher::Parallel,
[](const Sketcher::Constraint* constr) {
return boost::str(boost::format("Sketcher.Constraint('Parallel', %i, %i)")
% constr->First % constr->Second);
}},
{Sketcher::Perpendicular,
[](const Sketcher::Constraint* constr) {
if (constr->FirstPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %i, %i)")
% constr->First % constr->Second);
}
else if (constr->SecondPos == Sketcher::PointPos::none) {
return boost::str(
boost::format("Sketcher.Constraint('Perpendicular', %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second);
}
else {
return boost::str(
boost::format("Sketcher.Constraint('Perpendicular', %i, %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos));
}
}},
{Sketcher::Equal,
[](const Sketcher::Constraint* constr) {
return boost::str(boost::format("Sketcher.Constraint('Equal', %i, %i)")
% constr->First % constr->Second);
}},
{Sketcher::InternalAlignment,
[](const Sketcher::Constraint* constr) {
if (constr->InternalAlignmentIndex == EllipseMajorDiameter
|| constr->InternalAlignmentIndex == EllipseMinorDiameter) {
return boost::str(
boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i)")
% constr->internalAlignmentTypeToString() % constr->First
% constr->Second);
}
else if (constr->InternalAlignmentIndex == EllipseFocus1
|| constr->InternalAlignmentIndex == EllipseFocus2) {
return boost::str(
boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i)")
% constr->internalAlignmentTypeToString() % constr->First
% static_cast<int>(constr->FirstPos) % constr->Second);
}
else if (constr->InternalAlignmentIndex == BSplineControlPoint) {
return boost::str(
boost::format(
"Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i, %i)")
% constr->internalAlignmentTypeToString() % constr->First
% static_cast<int>(constr->FirstPos) % constr->Second
% constr->InternalAlignmentIndex);
}
THROWM(Base::ValueError, "PythonConverter: Constraint Alignment Type not supported")
}},
{ Sketcher::Distance,
[](const Sketcher::Constraint * constr){
if(constr->Second == GeoEnum::GeoUndef){
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %f)") %
constr->First % constr->getValue());
}
else if(constr->FirstPos == Sketcher::PointPos::none){
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %f)") %
constr->First % constr->Second % constr->getValue());
}
else if(constr->SecondPos == Sketcher::PointPos::none){
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %f)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % constr->getValue());
}
else {
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %i, %f)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second %
static_cast<int>(constr->SecondPos) % constr->getValue());
}
}},
{ Sketcher::Angle,
[](const Sketcher::Constraint * constr){
if(constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %f)") %
constr->First % constr->getValue());
}
else if(constr->SecondPos == Sketcher::PointPos::none){
return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %i, %f)") %
constr->First % constr->Second % constr->getValue());
}
else {
return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %i, %i, %i, %f)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second %
static_cast<int>(constr->SecondPos) % constr->getValue());
}
}},
{ Sketcher::DistanceX,
[](const Sketcher::Constraint * constr){
if(constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %f)") %
constr->First % constr->getValue());
}
else if(constr->SecondPos == Sketcher::PointPos::none){
return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %i, %f)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->getValue());
}
else {
return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %i, %i, %i, %f)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second %
static_cast<int>(constr->SecondPos) % constr->getValue());
}
}},
{ Sketcher::DistanceY,
[](const Sketcher::Constraint * constr){
if(constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %f)") %
constr->First % constr->getValue());
}
else if(constr->SecondPos == Sketcher::PointPos::none){
return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %i, %f)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->getValue());
}
else {
return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %i, %i, %i, %f)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second %
static_cast<int>(constr->SecondPos) % constr->getValue());
}
}},
{ Sketcher::Radius,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('Radius', %i, %f)") %
constr->First % constr->getValue());
}},
{ Sketcher::Diameter,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('Diameter', %i, %f)") %
constr->First % constr->getValue());
}},
{ Sketcher::Weight,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('Weight', %i, %f)") %
constr->First % constr->getValue());
}},
{ Sketcher::PointOnObject,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('PointOnObject', %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second);
}},
{ Sketcher::Symmetric,
[](const Sketcher::Constraint * constr){
if(constr->ThirdPos==Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('Symmetric', %i, %i, %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % static_cast<int>(constr->SecondPos) %
constr->Third);
}
else {
return boost::str(boost::format("Sketcher.Constraint('Symmetric', %i, %i, %i, %i, %i, %i)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % static_cast<int>(constr->SecondPos) %
constr->Third % static_cast<int>(constr->ThirdPos));
}
}},
{ Sketcher::SnellsLaw,
[](const Sketcher::Constraint * constr){
return boost::str(boost::format("Sketcher.Constraint('SnellsLaw', %i, %i, %i, %i, %i, %f)") %
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % static_cast<int>(constr->SecondPos) %
constr->Third % constr->getValue());
}},
};
THROWM(Base::ValueError,
"PythonConverter: Constraint Alignment Type not supported")
}},
{Sketcher::Distance,
[](const Sketcher::Constraint* constr) {
if (constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %f)")
% constr->First % constr->getValue());
}
else if (constr->FirstPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %f)")
% constr->First % constr->Second % constr->getValue());
}
else if (constr->SecondPos == Sketcher::PointPos::none) {
return boost::str(
boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %f)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% constr->getValue());
}
else {
return boost::str(
boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %i, %f)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos) % constr->getValue());
}
}},
{Sketcher::Angle,
[](const Sketcher::Constraint* constr) {
if (constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %f)")
% constr->First % constr->getValue());
}
else if (constr->SecondPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %i, %f)")
% constr->First % constr->Second % constr->getValue());
}
else {
return boost::str(
boost::format("Sketcher.Constraint('Angle', %i, %i, %i, %i, %f)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos) % constr->getValue());
}
}},
{Sketcher::DistanceX,
[](const Sketcher::Constraint* constr) {
if (constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %f)")
% constr->First % constr->getValue());
}
else if (constr->SecondPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %i, %f)")
% constr->First % static_cast<int>(constr->FirstPos)
% constr->getValue());
}
else {
return boost::str(
boost::format("Sketcher.Constraint('DistanceX', %i, %i, %i, %i, %f)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos) % constr->getValue());
}
}},
{Sketcher::DistanceY,
[](const Sketcher::Constraint* constr) {
if (constr->Second == GeoEnum::GeoUndef) {
return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %f)")
% constr->First % constr->getValue());
}
else if (constr->SecondPos == Sketcher::PointPos::none) {
return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %i, %f)")
% constr->First % static_cast<int>(constr->FirstPos)
% constr->getValue());
}
else {
return boost::str(
boost::format("Sketcher.Constraint('DistanceY', %i, %i, %i, %i, %f)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos) % constr->getValue());
}
}},
{Sketcher::Radius,
[](const Sketcher::Constraint* constr) {
return boost::str(boost::format("Sketcher.Constraint('Radius', %i, %f)")
% constr->First % constr->getValue());
}},
{Sketcher::Diameter,
[](const Sketcher::Constraint* constr) {
return boost::str(boost::format("Sketcher.Constraint('Diameter', %i, %f)")
% constr->First % constr->getValue());
}},
{Sketcher::Weight,
[](const Sketcher::Constraint* constr) {
return boost::str(boost::format("Sketcher.Constraint('Weight', %i, %f)")
% constr->First % constr->getValue());
}},
{Sketcher::PointOnObject,
[](const Sketcher::Constraint* constr) {
return boost::str(boost::format("Sketcher.Constraint('PointOnObject', %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos)
% constr->Second);
}},
{Sketcher::Symmetric,
[](const Sketcher::Constraint* constr) {
if (constr->ThirdPos == Sketcher::PointPos::none) {
return boost::str(
boost::format("Sketcher.Constraint('Symmetric', %i, %i, %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos) % constr->Third);
}
else {
return boost::str(
boost::format("Sketcher.Constraint('Symmetric', %i, %i, %i, %i, %i, %i)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos) % constr->Third
% static_cast<int>(constr->ThirdPos));
}
}},
{Sketcher::SnellsLaw,
[](const Sketcher::Constraint* constr) {
return boost::str(
boost::format("Sketcher.Constraint('SnellsLaw', %i, %i, %i, %i, %i, %f)")
% constr->First % static_cast<int>(constr->FirstPos) % constr->Second
% static_cast<int>(constr->SecondPos) % constr->Third % constr->getValue());
}},
};
auto result = converterMap.find(constraint->Type);
if( result == converterMap.end())
if (result == converterMap.end())
THROWM(Base::ValueError, "PythonConverter: Constraint Type not supported")
auto creator = result->second;

View File

@@ -24,12 +24,14 @@
#ifndef SKETCHER_PythonConverter_H
#define SKETCHER_PythonConverter_H
namespace Part {
class Geometry;
namespace Part
{
class Geometry;
}
namespace Sketcher {
class Constraint;
namespace Sketcher
{
class Constraint;
/** @brief Class for generating python code
* @details
@@ -37,38 +39,38 @@ namespace Sketcher {
* create such objects.
*/
class SketcherExport PythonConverter {
class SketcherExport PythonConverter
{
class SingleGeometry {
class SingleGeometry
{
public:
std::string creation;
bool construction;
};
public:
explicit PythonConverter() = delete;
~PythonConverter() = delete;
/// Convert a geometry into the string representing the command creating it
static std::string convert(const Part::Geometry * geo);
static std::string convert(const Part::Geometry* geo);
/// Convert a vector of geometries into the string representing the command creating them
static std::string convert(const std::string & doc, const std::vector<Part::Geometry *> & geos);
static std::string convert(const std::string& doc, const std::vector<Part::Geometry*>& geos);
static std::string convert(const Sketcher::Constraint * constraint);
static std::string convert(const Sketcher::Constraint* constraint);
static std::string convert(const std::string & doc, const std::vector<Sketcher::Constraint *> & constraints);
static std::string convert(const std::string& doc,
const std::vector<Sketcher::Constraint*>& constraints);
private:
static SingleGeometry process(const Part::Geometry * geo);
static std::string process(const Sketcher::Constraint * constraint);
static SingleGeometry process(const Part::Geometry* geo);
static std::string process(const Sketcher::Constraint* constraint);
};
} // namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_PythonConverter_H
#endif// SKETCHER_PythonConverter_H

File diff suppressed because it is too large Load Diff

View File

@@ -34,10 +34,10 @@
namespace Sketcher
{
// Forward declarations
class SolverGeometryExtension;
// Forward declarations
class SolverGeometryExtension;
class SketcherExport Sketch :public Base::Persistence
class SketcherExport Sketch: public Base::Persistence
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
@@ -47,52 +47,56 @@ public:
// from base class
unsigned int getMemSize() const override;
void Save(Base::Writer &/*writer*/) const override;
void Restore(Base::XMLReader &/*reader*/) override;
void Save(Base::Writer& /*writer*/) const override;
void Restore(Base::XMLReader& /*reader*/) override;
/// solve the actual set up sketch
int solve();
/// resets the solver
int resetSolver();
/// get standard (aka fine) solver precision
double getSolverPrecision(){ return GCSsys.getFinePrecision(); }
double getSolverPrecision()
{
return GCSsys.getFinePrecision();
}
/// delete all geometry and constraints, leave an empty sketch
void clear();
/** set the sketch up with geoms and constraints
*
* returns the degree of freedom of a sketch and calculates a list of
* conflicting constraints
*
* 0 degrees of freedom correspond to a fully constrained sketch
* -1 degrees of freedom correspond to an over-constrained sketch
* positive degrees of freedom correspond to an under-constrained sketch
*
* an over-constrained sketch will always contain conflicting constraints
* a fully constrained or under-constrained sketch may contain conflicting
* constraints or may not
*/
int setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Constraint *> &ConstraintList,
int extGeoCount=0);
*
* returns the degree of freedom of a sketch and calculates a list of
* conflicting constraints
*
* 0 degrees of freedom correspond to a fully constrained sketch
* -1 degrees of freedom correspond to an over-constrained sketch
* positive degrees of freedom correspond to an under-constrained sketch
*
* an over-constrained sketch will always contain conflicting constraints
* a fully constrained or under-constrained sketch may contain conflicting
* constraints or may not
*/
int setUpSketch(const std::vector<Part::Geometry*>& GeoList,
const std::vector<Constraint*>& ConstraintList, int extGeoCount = 0);
/// return the actual geometry of the sketch a TopoShape
Part::TopoShape toShape() const;
/// add unspecified geometry
int addGeometry(const Part::Geometry *geo, bool fixed=false);
int addGeometry(const Part::Geometry* geo, bool fixed = false);
/// add unspecified geometry
int addGeometry(const std::vector<Part::Geometry *> &geo, bool fixed=false);
/// add unspecified geometry, where each element's "fixed" status is given by the blockedGeometry array
int addGeometry(const std::vector<Part::Geometry *> &geo,
const std::vector<bool> &blockedGeometry);
int addGeometry(const std::vector<Part::Geometry*>& geo, bool fixed = false);
/// add unspecified geometry, where each element's "fixed" status is given by the
/// blockedGeometry array
int addGeometry(const std::vector<Part::Geometry*>& geo,
const std::vector<bool>& blockedGeometry);
/// get boolean list indicating whether the geometry is to be blocked or not
void getBlockedGeometry(std::vector<bool> & blockedGeometry,
std::vector<bool> & unenforceableConstraints,
const std::vector<Constraint *> &ConstraintList) const;
void getBlockedGeometry(std::vector<bool>& blockedGeometry,
std::vector<bool>& unenforceableConstraints,
const std::vector<Constraint*>& ConstraintList) const;
/// returns the actual geometry
std::vector<Part::Geometry *> extractGeometry(bool withConstructionElements=true,
bool withExternalElements=false) const;
std::vector<Part::Geometry*> extractGeometry(bool withConstructionElements = true,
bool withExternalElements = false) const;
GeoListFacade extractGeoListFacade() const;
void updateExtension(int geoId, std::unique_ptr<Part::GeometryExtension> && ext);
void updateExtension(int geoId, std::unique_ptr<Part::GeometryExtension>&& ext);
/// get the geometry as python objects
Py::Tuple getPyGeometry() const;
@@ -102,39 +106,67 @@ public:
Base::Vector3d getPoint(int geoId, PointPos pos) const;
// Inline methods
inline bool hasConflicts() const { return !Conflicting.empty(); }
inline const std::vector<int> &getConflicting() const { return Conflicting; }
inline bool hasRedundancies() const { return !Redundant.empty(); }
inline const std::vector<int> &getRedundant() const { return Redundant; }
inline bool hasPartialRedundancies() const { return !PartiallyRedundant.empty(); }
inline const std::vector<int> &getPartiallyRedundant() const { return PartiallyRedundant; }
inline bool hasConflicts() const
{
return !Conflicting.empty();
}
inline const std::vector<int>& getConflicting() const
{
return Conflicting;
}
inline bool hasRedundancies() const
{
return !Redundant.empty();
}
inline const std::vector<int>& getRedundant() const
{
return Redundant;
}
inline bool hasPartialRedundancies() const
{
return !PartiallyRedundant.empty();
}
inline const std::vector<int>& getPartiallyRedundant() const
{
return PartiallyRedundant;
}
inline float getSolveTime() const { return SolveTime; }
inline float getSolveTime() const
{
return SolveTime;
}
inline bool hasMalformedConstraints() const
{
return !MalformedConstraints.empty();
}
inline const std::vector<int>& getMalformedConstraints() const
{
return MalformedConstraints;
}
inline bool hasMalformedConstraints() const { return !MalformedConstraints.empty(); }
inline const std::vector<int> &getMalformedConstraints() const { return MalformedConstraints; }
public:
std::set < std::pair< int, Sketcher::PointPos>> getDependencyGroup(int geoId, PointPos pos) const;
std::set<std::pair<int, Sketcher::PointPos>> getDependencyGroup(int geoId, PointPos pos) const;
std::shared_ptr<SolverGeometryExtension> getSolverExtension(int geoId) const;
public:
/** set the datum of a distance or angle constraint to a certain value and solve
* This can cause the solving to fail!
*/
* This can cause the solving to fail!
*/
int setDatum(int constrId, double value);
/** initializes a point (or curve) drag by setting the current
* sketch status as a reference
*/
int initMove(int geoId, PointPos pos, bool fine=true);
* sketch status as a reference
*/
int initMove(int geoId, PointPos pos, bool fine = true);
/** Initializes a B-spline piece drag by setting the current
* sketch status as a reference. Only moves piece around `firstPoint`.
*/
int initBSplinePieceMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint, bool fine=true);
* sketch status as a reference. Only moves piece around `firstPoint`.
*/
int initBSplinePieceMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint,
bool fine = true);
/** Resets the initialization of a point or curve drag
*/
@@ -145,105 +177,112 @@ public:
int limitBSplineMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint);
/** move this point (or curve) to a new location and solve.
* This will introduce some additional weak constraints expressing
* a condition for satisfying the new point location!
* The relative flag permits moving relatively to the current position
*/
int movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative=false);
* This will introduce some additional weak constraints expressing
* a condition for satisfying the new point location!
* The relative flag permits moving relatively to the current position
*/
int movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative = false);
/**
* Sets whether the initial solution should be recalculated while dragging after a certain distance from the previous drag point
* for smoother dragging operation.
* Sets whether the initial solution should be recalculated while dragging after a certain
* distance from the previous drag point for smoother dragging operation.
*/
bool getRecalculateInitialSolutionWhileMovingPoint() const
{return RecalculateInitialSolutionWhileMovingPoint;}
{
return RecalculateInitialSolutionWhileMovingPoint;
}
void setRecalculateInitialSolutionWhileMovingPoint(bool recalculateInitialSolutionWhileMovingPoint)
{RecalculateInitialSolutionWhileMovingPoint = recalculateInitialSolutionWhileMovingPoint;}
void
setRecalculateInitialSolutionWhileMovingPoint(bool recalculateInitialSolutionWhileMovingPoint)
{
RecalculateInitialSolutionWhileMovingPoint = recalculateInitialSolutionWhileMovingPoint;
}
/// add dedicated geometry
//@{
/// add a point
int addPoint(const Part::GeomPoint &point, bool fixed=false);
int addPoint(const Part::GeomPoint& point, bool fixed = false);
/// add an infinite line
int addLine(const Part::GeomLineSegment &line, bool fixed=false);
int addLine(const Part::GeomLineSegment& line, bool fixed = false);
/// add a line segment
int addLineSegment(const Part::GeomLineSegment &lineSegment, bool fixed=false);
int addLineSegment(const Part::GeomLineSegment& lineSegment, bool fixed = false);
/// add a arc (circle segment)
int addArc(const Part::GeomArcOfCircle &circleSegment, bool fixed=false);
int addArc(const Part::GeomArcOfCircle& circleSegment, bool fixed = false);
/// add a circle
int addCircle(const Part::GeomCircle &circle, bool fixed=false);
int addCircle(const Part::GeomCircle& circle, bool fixed = false);
/// add an ellipse
int addEllipse(const Part::GeomEllipse &ellipse, bool fixed=false);
int addEllipse(const Part::GeomEllipse& ellipse, bool fixed = false);
/// add an arc of ellipse
int addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool fixed=false);
int addArcOfEllipse(const Part::GeomArcOfEllipse& ellipseSegment, bool fixed = false);
/// add an arc of hyperbola
int addArcOfHyperbola(const Part::GeomArcOfHyperbola &hyperbolaSegment, bool fixed=false);
int addArcOfHyperbola(const Part::GeomArcOfHyperbola& hyperbolaSegment, bool fixed = false);
/// add an arc of parabola
int addArcOfParabola(const Part::GeomArcOfParabola &parabolaSegment, bool fixed=false);
int addArcOfParabola(const Part::GeomArcOfParabola& parabolaSegment, bool fixed = false);
/// add a BSpline
int addBSpline(const Part::GeomBSplineCurve &spline, bool fixed=false);
int addBSpline(const Part::GeomBSplineCurve& spline, bool fixed = false);
//@}
/// constraints
//@{
/// add all constraints in the list
int addConstraints(const std::vector<Constraint *> &ConstraintList);
int addConstraints(const std::vector<Constraint*>& ConstraintList);
/// add all constraints in the list, provided that are enforceable
int addConstraints(const std::vector<Constraint *> &ConstraintList,
const std::vector<bool> & unenforceableConstraints);
int addConstraints(const std::vector<Constraint*>& ConstraintList,
const std::vector<bool>& unenforceableConstraints);
/// add one constraint to the sketch
int addConstraint(const Constraint *constraint);
int addConstraint(const Constraint* constraint);
/**
* add a fixed X coordinate constraint to a point
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addCoordinateXConstraint(int geoId, PointPos pos, double * value, bool driving = true);
* add a fixed X coordinate constraint to a point
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addCoordinateXConstraint(int geoId, PointPos pos, double* value, bool driving = true);
/**
* add a fixed Y coordinate constraint to a point
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addCoordinateYConstraint(int geoId, PointPos pos, double * value, bool driving = true);
* add a fixed Y coordinate constraint to a point
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addCoordinateYConstraint(int geoId, PointPos pos, double* value, bool driving = true);
/**
* add a horizontal distance constraint to two points or line ends
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceXConstraint(int geoId, double * value, bool driving = true);
* add a horizontal distance constraint to two points or line ends
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceXConstraint(int geoId, double* value, bool driving = true);
/**
* add a horizontal distance constraint to two points or line ends
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value, bool driving = true);
* add a horizontal distance constraint to two points or line ends
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double* value,
bool driving = true);
/**
* add a vertical distance constraint to two points or line ends
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceYConstraint(int geoId, double * value, bool driving = true);
* add a vertical distance constraint to two points or line ends
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceYConstraint(int geoId, double* value, bool driving = true);
/**
* add a vertical distance constraint to two points or line ends
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value, bool driving = true);
* add a vertical distance constraint to two points or line ends
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double* value,
bool driving = true);
/// add a horizontal constraint to a geometry
int addHorizontalConstraint(int geoId);
int addHorizontalConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2);
@@ -253,37 +292,39 @@ public:
/// add a coincident constraint to two points of two geometries
int addPointCoincidentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2);
/**
* add a length or distance constraint
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceConstraint(int geoId1, double * value, bool driving = true);
* add a length or distance constraint
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceConstraint(int geoId1, double* value, bool driving = true);
/**
* add a length or distance constraint
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double * value, bool driving = true);
* add a length or distance constraint
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double* value,
bool driving = true);
/**
* add a length or distance constraint
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value, bool driving = true);
* add a length or distance constraint
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double* value,
bool driving = true);
/**
* add a length or distance constraint
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceConstraint(int geoId1, int geoId2, double * value, bool driving = true);
* add a length or distance constraint
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDistanceConstraint(int geoId1, int geoId2, double* value, bool driving = true);
/// add a parallel constraint between two lines
int addParallelConstraint(int geoId1, int geoId2);
@@ -291,22 +332,14 @@ public:
int addPerpendicularConstraint(int geoId1, int geoId2);
/// add a tangency constraint between two geometries
int addTangentConstraint(int geoId1, int geoId2);
int addTangentLineAtBSplineKnotConstraint(int checkedlinegeoId, int checkedbsplinegeoId, int checkedknotgeoid);
int addTangentLineEndpointAtBSplineKnotConstraint(int checkedlinegeoId, PointPos endpointPos, int checkedbsplinegeoId, int checkedknotgeoid);
int addAngleAtPointConstraint(
int geoId1, PointPos pos1,
int geoId2, PointPos pos2,
int geoId3, PointPos pos3,
double * value,
ConstraintType cTyp, bool driving = true);
/**
* add a radius constraint on a circle or an arc
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addRadiusConstraint(int geoId, double * value, bool driving = true);
int addTangentLineAtBSplineKnotConstraint(int checkedlinegeoId, int checkedbsplinegeoId,
int checkedknotgeoid);
int addTangentLineEndpointAtBSplineKnotConstraint(int checkedlinegeoId, PointPos endpointPos,
int checkedbsplinegeoId,
int checkedknotgeoid);
int addAngleAtPointConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3,
PointPos pos3, double* value, ConstraintType cTyp,
bool driving = true);
/**
* add a radius constraint on a circle or an arc
*
@@ -314,65 +347,75 @@ public:
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDiameterConstraint(int geoId, double * value, bool driving = true);
int addRadiusConstraint(int geoId, double* value, bool driving = true);
/**
* add an angle constraint on a line or between two lines
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addAngleConstraint(int geoId, double * value, bool driving = true);
* add a radius constraint on a circle or an arc
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addDiameterConstraint(int geoId, double* value, bool driving = true);
/**
* add an angle constraint on a line or between two lines
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addAngleConstraint(int geoId1, int geoId2, double * value, bool driving = true);
* add an angle constraint on a line or between two lines
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addAngleConstraint(int geoId, double* value, bool driving = true);
/**
* add an angle constraint on a line or between two lines
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value, bool driving = true);
* add an angle constraint on a line or between two lines
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addAngleConstraint(int geoId1, int geoId2, double* value, bool driving = true);
/**
* add angle-via-point constraint between any two curves
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addAngleViaPointConstraint(int geoId1, int geoId2, int geoId3, PointPos pos3, double value, bool driving = true);
* add an angle constraint on a line or between two lines
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double* value,
bool driving = true);
/**
* add angle-via-point constraint between any two curves
*
* double * value is a pointer to double allocated in the heap, containing the
* constraint value and already inserted into either the FixParameters or
* Parameters array, as the case may be.
*/
int addAngleViaPointConstraint(int geoId1, int geoId2, int geoId3, PointPos pos3, double value,
bool driving = true);
/// add an equal length or radius constraints between two lines or between circles and arcs
int addEqualConstraint(int geoId1, int geoId2);
/// add a point on line constraint
int addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2, bool driving = true);
/// add a point on B-spline constraint: needs a parameter
int addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2,double* pointparam, bool driving = true);
int addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2, double* pointparam,
bool driving = true);
/// add a symmetric constraint between two points with respect to a line
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3);
/// add a symmetric constraint between three points, the last point is in the middle of the first two
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3, PointPos pos3);
/// add a symmetric constraint between three points, the last point is in the middle of the
/// first two
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3,
PointPos pos3);
/**
* add a snell's law constraint
*
* double * value and double * second are each a pointer to double
* allocated in the heap and already inserted into either the
* FixParameters or Parameters array, as the case may be.
*
* value must contain the constraint value (the ratio of n2/n1)
* second may be initialized to any value, however the solver will
* provide n1 in value and n2 in second.
*/
int addSnellsLawConstraint(int geoIdRay1, PointPos posRay1,
int geoIdRay2, PointPos posRay2,
int geoIdBnd,
double * value,
double * second, bool driving = true);
* add a snell's law constraint
*
* double * value and double * second are each a pointer to double
* allocated in the heap and already inserted into either the
* FixParameters or Parameters array, as the case may be.
*
* value must contain the constraint value (the ratio of n2/n1)
* second may be initialized to any value, however the solver will
* provide n1 in value and n2 in second.
*/
int addSnellsLawConstraint(int geoIdRay1, PointPos posRay1, int geoIdRay2, PointPos posRay2,
int geoIdBnd, double* value, double* second, bool driving = true);
//@}
/// Internal Alignment constraints
@@ -392,29 +435,37 @@ public:
int addInternalAlignmentKnotPoint(int geoId1, int geoId2, int knotindex);
//@}
public:
//This func is to be used during angle-via-point constraint creation. It calculates
//the angle between geoId1,geoId2 at point px,py. The point should be on both curves,
//otherwise the result will be systematically off (but smoothly approach the correct
//value as the point approaches intersection of curves).
double calculateAngleViaPoint(int geoId1, int geoId2, double px, double py );
// This func is to be used during angle-via-point constraint creation. It calculates
// the angle between geoId1,geoId2 at point px,py. The point should be on both curves,
// otherwise the result will be systematically off (but smoothly approach the correct
// value as the point approaches intersection of curves).
double calculateAngleViaPoint(int geoId1, int geoId2, double px, double py);
//This is to be used for rendering of angle-via-point constraint.
// This is to be used for rendering of angle-via-point constraint.
Base::Vector3d calculateNormalAtPoint(int geoIdCurve, double px, double py) const;
//icstr should be the value returned by addXXXXConstraint
//see more info in respective function in GCS.
double calculateConstraintError(int icstr) { return GCSsys.calculateConstraintErrorByTag(icstr);}
// icstr should be the value returned by addXXXXConstraint
// see more info in respective function in GCS.
double calculateConstraintError(int icstr)
{
return GCSsys.calculateConstraintErrorByTag(icstr);
}
/// Returns the size of the Geometry
int getGeometrySize() const {return Geoms.size();}
int getGeometrySize() const
{
return Geoms.size();
}
enum GeoType {
None = 0,
Point = 1, // 1 Point(start), 2 Parameters(x,y)
Line = 2, // 2 Points(start,end), 4 Parameters(x1,y1,x2,y2)
Arc = 3, // 3 Points(start,end,mid), (4)+5 Parameters((x1,y1,x2,y2),x,y,r,a1,a2)
Circle = 4, // 1 Point(mid), 3 Parameters(x,y,r)
Ellipse = 5, // 1 Point(mid), 5 Parameters(x,y,r1,r2,phi) phi=angle xaxis of ellipse with respect of sketch xaxis
enum GeoType
{
None = 0,
Point = 1, // 1 Point(start), 2 Parameters(x,y)
Line = 2, // 2 Points(start,end), 4 Parameters(x1,y1,x2,y2)
Arc = 3, // 3 Points(start,end,mid), (4)+5 Parameters((x1,y1,x2,y2),x,y,r,a1,a2)
Circle = 4, // 1 Point(mid), 3 Parameters(x,y,r)
Ellipse = 5,// 1 Point(mid), 5 Parameters(x,y,r1,r2,phi)
// phi=angle xaxis of ellipse with respect of sketch xaxis
ArcOfEllipse = 6,
ArcOfHyperbola = 7,
ArcOfParabola = 8,
@@ -425,33 +476,45 @@ protected:
float SolveTime;
bool RecalculateInitialSolutionWhileMovingPoint;
// regulates a second solve for cases where there result of having update the geometry (e.g. via OCCT)
// needs to be taken into account by the solver (for example to provide the right value of non-driving constraints)
// regulates a second solve for cases where there result of having update the geometry (e.g. via
// OCCT) needs to be taken into account by the solver (for example to provide the right value of
// non-driving constraints)
bool resolveAfterGeometryUpdated;
protected:
/// container element to store and work with the geometric elements of this sketch
struct GeoDef {
GeoDef() : geo(nullptr),type(None),external(false),index(-1),
startPointId(-1),midPointId(-1),endPointId(-1) {}
Part::Geometry * geo; // pointer to the geometry
GeoType type; // type of the geometry
bool external; // flag for external geometries
int index; // index in the corresponding storage vector (Lines, Arcs, Circles, ...)
int startPointId; // index in Points of the start point of this geometry
int midPointId; // index in Points of the start point of this geometry
int endPointId; // index in Points of the end point of this geometry
struct GeoDef
{
GeoDef()
: geo(nullptr),
type(None),
external(false),
index(-1),
startPointId(-1),
midPointId(-1),
endPointId(-1)
{}
Part::Geometry* geo;// pointer to the geometry
GeoType type; // type of the geometry
bool external; // flag for external geometries
int index; // index in the corresponding storage vector (Lines, Arcs, Circles, ...)
int startPointId; // index in Points of the start point of this geometry
int midPointId; // index in Points of the start point of this geometry
int endPointId; // index in Points of the end point of this geometry
};
/// container element to store and work with the constraints of this sketch
struct ConstrDef {
ConstrDef() : constr(nullptr)
, driving(true)
, value(nullptr)
, secondvalue(nullptr) {}
Constraint * constr; // pointer to the constraint
bool driving;
double * value;
double * secondvalue; // this is needed for SnellsLaw
struct ConstrDef
{
ConstrDef()
: constr(nullptr),
driving(true),
value(nullptr),
secondvalue(nullptr)
{}
Constraint* constr;// pointer to the constraint
bool driving;
double* value;
double* secondvalue;// this is needed for SnellsLaw
};
std::vector<GeoDef> Geoms;
@@ -463,27 +526,30 @@ protected:
std::vector<int> PartiallyRedundant;
std::vector<int> MalformedConstraints;
std::vector<double *> pDependentParametersList;
std::vector<double*> pDependentParametersList;
// map of geoIds to corresponding solverextensions. This is useful when solved geometry is NOT to be assigned to the SketchObject
// map of geoIds to corresponding solverextensions. This is useful when solved geometry is NOT
// to be assigned to the SketchObject
std::vector<std::shared_ptr<SolverGeometryExtension>> solverExtensions;
// maps a geoid corresponding to an internalgeometry (focus,knot,pole) to the geometry it defines (ellipse, hyperbola, B-Spline)
std::map< int, int > internalAlignmentGeometryMap;
// maps a geoid corresponding to an internalgeometry (focus,knot,pole) to the geometry it
// defines (ellipse, hyperbola, B-Spline)
std::map<int, int> internalAlignmentGeometryMap;
std::vector < std::set < std::pair< int, Sketcher::PointPos>>> pDependencyGroups;
std::vector<std::set<std::pair<int, Sketcher::PointPos>>> pDependencyGroups;
// this map is intended to convert a parameter (double *) into a GeoId/PointPos and parameter number
std::map<double *, std::tuple<int, Sketcher::PointPos, int>> param2geoelement;
// this map is intended to convert a parameter (double *) into a GeoId/PointPos and parameter
// number
std::map<double*, std::tuple<int, Sketcher::PointPos, int>> param2geoelement;
// solving parameters
std::vector<double*> Parameters; // with memory allocation
std::vector<double*> DrivenParameters; // with memory allocation
std::vector<double*> FixParameters; // with memory allocation
std::vector<double*> Parameters; // with memory allocation
std::vector<double*> DrivenParameters;// with memory allocation
std::vector<double*> FixParameters; // with memory allocation
std::vector<double> MoveParameters, InitParameters;
std::vector<GCS::Point> Points;
std::vector<GCS::Line> Lines;
std::vector<GCS::Arc> Arcs;
std::vector<GCS::Point> Points;
std::vector<GCS::Line> Lines;
std::vector<GCS::Arc> Arcs;
std::vector<GCS::Circle> Circles;
std::vector<GCS::Ellipse> Ellipses;
std::vector<GCS::ArcOfEllipse> ArcsOfEllipse;
@@ -499,36 +565,108 @@ protected:
public:
GCS::Algorithm defaultSolver;
GCS::Algorithm defaultSolverRedundant;
inline void setDogLegGaussStep(GCS::DogLegGaussStep mode){GCSsys.dogLegGaussStep=mode;}
inline void setDebugMode(GCS::DebugMode mode) {debugMode=mode;GCSsys.debugMode=mode;}
inline GCS::DebugMode getDebugMode() {return debugMode;}
inline void setMaxIter(int maxiter){GCSsys.maxIter=maxiter;}
inline void setMaxIterRedundant(int maxiter){GCSsys.maxIterRedundant=maxiter;}
inline void setSketchSizeMultiplier(bool mult){GCSsys.sketchSizeMultiplier=mult;}
inline void setSketchSizeMultiplierRedundant(bool mult){GCSsys.sketchSizeMultiplierRedundant=mult;}
inline void setConvergence(double conv){GCSsys.convergence=conv;}
inline void setConvergenceRedundant(double conv){GCSsys.convergenceRedundant=conv;}
inline void setQRAlgorithm(GCS::QRAlgorithm alg){GCSsys.qrAlgorithm=alg;}
inline GCS::QRAlgorithm getQRAlgorithm(){return GCSsys.qrAlgorithm;}
inline void setQRPivotThreshold(double val){GCSsys.qrpivotThreshold=val;}
inline void setLM_eps(double val){GCSsys.LM_eps=val;}
inline void setLM_eps1(double val){GCSsys.LM_eps1=val;}
inline void setLM_tau(double val){GCSsys.LM_tau=val;}
inline void setDL_tolg(double val){GCSsys.DL_tolg=val;}
inline void setDL_tolx(double val){GCSsys.DL_tolx=val;}
inline void setDL_tolf(double val){GCSsys.DL_tolf=val;}
inline void setLM_epsRedundant(double val){GCSsys.LM_epsRedundant=val;}
inline void setLM_eps1Redundant(double val){GCSsys.LM_eps1Redundant=val;}
inline void setLM_tauRedundant(double val){GCSsys.LM_tauRedundant=val;}
inline void setDL_tolgRedundant(double val){GCSsys.DL_tolgRedundant=val;}
inline void setDL_tolxRedundant(double val){GCSsys.DL_tolxRedundant=val;}
inline void setDL_tolfRedundant(double val){GCSsys.DL_tolfRedundant=val;}
inline void setDogLegGaussStep(GCS::DogLegGaussStep mode)
{
GCSsys.dogLegGaussStep = mode;
}
inline void setDebugMode(GCS::DebugMode mode)
{
debugMode = mode;
GCSsys.debugMode = mode;
}
inline GCS::DebugMode getDebugMode()
{
return debugMode;
}
inline void setMaxIter(int maxiter)
{
GCSsys.maxIter = maxiter;
}
inline void setMaxIterRedundant(int maxiter)
{
GCSsys.maxIterRedundant = maxiter;
}
inline void setSketchSizeMultiplier(bool mult)
{
GCSsys.sketchSizeMultiplier = mult;
}
inline void setSketchSizeMultiplierRedundant(bool mult)
{
GCSsys.sketchSizeMultiplierRedundant = mult;
}
inline void setConvergence(double conv)
{
GCSsys.convergence = conv;
}
inline void setConvergenceRedundant(double conv)
{
GCSsys.convergenceRedundant = conv;
}
inline void setQRAlgorithm(GCS::QRAlgorithm alg)
{
GCSsys.qrAlgorithm = alg;
}
inline GCS::QRAlgorithm getQRAlgorithm()
{
return GCSsys.qrAlgorithm;
}
inline void setQRPivotThreshold(double val)
{
GCSsys.qrpivotThreshold = val;
}
inline void setLM_eps(double val)
{
GCSsys.LM_eps = val;
}
inline void setLM_eps1(double val)
{
GCSsys.LM_eps1 = val;
}
inline void setLM_tau(double val)
{
GCSsys.LM_tau = val;
}
inline void setDL_tolg(double val)
{
GCSsys.DL_tolg = val;
}
inline void setDL_tolx(double val)
{
GCSsys.DL_tolx = val;
}
inline void setDL_tolf(double val)
{
GCSsys.DL_tolf = val;
}
inline void setLM_epsRedundant(double val)
{
GCSsys.LM_epsRedundant = val;
}
inline void setLM_eps1Redundant(double val)
{
GCSsys.LM_eps1Redundant = val;
}
inline void setLM_tauRedundant(double val)
{
GCSsys.LM_tauRedundant = val;
}
inline void setDL_tolgRedundant(double val)
{
GCSsys.DL_tolgRedundant = val;
}
inline void setDL_tolxRedundant(double val)
{
GCSsys.DL_tolxRedundant = val;
}
inline void setDL_tolfRedundant(double val)
{
GCSsys.DL_tolfRedundant = val;
}
protected:
GCS::DebugMode debugMode;
private:
bool updateGeometry();
bool updateNonDrivingConstraints();
@@ -536,9 +674,9 @@ private:
void clearTemporaryConstraints();
void buildInternalAlignmentGeometryMap(const std::vector<Constraint *> &constraintList);
void buildInternalAlignmentGeometryMap(const std::vector<Constraint*>& constraintList);
int internalSolve(std::string & solvername, int level = 0);
int internalSolve(std::string& solvername, int level = 0);
/// checks if the index bounds and converts negative indices to positive
int checkGeoId(int geoId) const;
@@ -555,63 +693,71 @@ private:
*
* This is important because 1) can be pre-fixed when creating geometry and constraints
* before GCS::diagnose() via initSolution(). This is important because if no other constraint
* affect the geometry, the geometry parameters won't even appear in the Jacobian, and they won't
* be reported as dependent parameters.
* affect the geometry, the geometry parameters won't even appear in the Jacobian, and they
* won't be reported as dependent parameters.
*
* On the contrary 2) cannot be pre-fixed because it would lead to redundant constraints and requires
* a post-analysis, see analyseBlockedConstraintDependentParameters, to fix just the parameters that
* fulfil the dependacy groups.
* On the contrary 2) cannot be pre-fixed because it would lead to redundant constraints and
* requires a post-analysis, see analyseBlockedConstraintDependentParameters, to fix just the
* parameters that fulfil the dependacy groups.
*/
bool analyseBlockedGeometry( const std::vector<Part::Geometry *> &internalGeoList,
const std::vector<Constraint *> &constraintList,
std::vector<bool> &onlyblockedGeometry,
std::vector<int> &blockedGeoIds) const;
bool analyseBlockedGeometry(const std::vector<Part::Geometry*>& internalGeoList,
const std::vector<Constraint*>& constraintList,
std::vector<bool>& onlyblockedGeometry,
std::vector<int>& blockedGeoIds) const;
/* This function performs a post-analysis of blocked geometries (see analyseBlockedGeometry for more detail
* on the pre-analysis).
/* This function performs a post-analysis of blocked geometries (see analyseBlockedGeometry for
* more detail on the pre-analysis).
*
* Basically identifies which parameters shall be fixed to make geometries having blocking constraints fixed,
* while not leading to redundant/conflicting constraints. These parameters must belong to blocked geometry. This
* is, groups may comprise parameters belonging to blocked geometry and parameters belonging to unconstrained geometry.
* It is licit that the latter remain as dependent parameters. The former are referred to as "blockable parameters".
* Basically identifies which parameters shall be fixed to make geometries having blocking
* constraints fixed, while not leading to redundant/conflicting constraints. These parameters
* must belong to blocked geometry. This is, groups may comprise parameters belonging to blocked
* geometry and parameters belonging to unconstrained geometry. It is licit that the latter
* remain as dependent parameters. The former are referred to as "blockable parameters".
*
* Extending this concept, there may be unsatisfiable groups (because they do not comprise any bloackable parameter),
* and it is the desired outcome NOT to satisfy such groups.
* Extending this concept, there may be unsatisfiable groups (because they do not comprise any
* bloackable parameter), and it is the desired outcome NOT to satisfy such groups.
*
* There is not a single combination of fixed parameters from the blockable parameters that satisfy all the dependency
* groups. However:
* There is not a single combination of fixed parameters from the blockable parameters that
* satisfy all the dependency groups. However:
*
* 1) some combinations do not satisfy all the dependency groups that must be satisfied (e.g. fixing one
* group containing two blockable parameters with a given one may result in another group, fixable only by the former, not
* to be satisfied). This leads, in a subsequent diagnosis, to satisfiable unsatisfied groups.
* 1) some combinations do not satisfy all the dependency groups that must be satisfied (e.g.
* fixing one group containing two blockable parameters with a given one may result in another
* group, fixable only by the former, not to be satisfied). This leads, in a subsequent
* diagnosis, to satisfiable unsatisfied groups.
*
* 2) some combinations lead to partially redundant constraints, that the solver will silently drop in a subsequent diagnosis,
* thereby reducing the rank of the system fixing less than it should.
* 2) some combinations lead to partially redundant constraints, that the solver will silently
* drop in a subsequent diagnosis, thereby reducing the rank of the system fixing less than it
* should.
*
* Implementation rationale (at this time):
*
* The implementation is on the order of the groups provided by the QR decomposition used to reveal the parameters
* (see System::identifyDependentParameters in GCS). Zeros are made over the pilot of the full R matrix of the QR decomposition,
* which is a top triangular matrix.This, together with the permutation matrix, allow to know groups of dependent parameters
* (cols between rank and full size). Each group refers to a new parameter not affected by the rank in combination with other free
* parameters intervening in the rank (because of the triangular shape of the R matrix). This results in that each the first column
* between the rank and the full size, may only depend on a number of parameters, while the last full size column may be dependent on
* any amount of previously introduced parameters.
* The implementation is on the order of the groups provided by the QR decomposition used to
* reveal the parameters (see System::identifyDependentParameters in GCS). Zeros are made over
* the pilot of the full R matrix of the QR decomposition, which is a top triangular
* matrix.This, together with the permutation matrix, allow to know groups of dependent
* parameters (cols between rank and full size). Each group refers to a new parameter not
* affected by the rank in combination with other free parameters intervening in the rank
* (because of the triangular shape of the R matrix). This results in that each the first column
* between the rank and the full size, may only depend on a number of parameters, while the last
* full size column may be dependent on any amount of previously introduced parameters.
*
* Thus the rationale is: start from the last group (having **potentially** the larger amount of parameters) and selecting as blocking
* for that group the latest blockable parameter. Because previous groups do not have access to the last parameter, this can never
* interfere with previous groups. However, because the last parameter may not be a blockable one, there is a risk of selecting a parameter
* common with other group, albeit the probability is reduced and probably (I have not demonstrated it though and I am not sure), it leads
* to the right solution in one iteration.
* Thus the rationale is: start from the last group (having **potentially** the larger amount of
* parameters) and selecting as blocking for that group the latest blockable parameter. Because
* previous groups do not have access to the last parameter, this can never interfere with
* previous groups. However, because the last parameter may not be a blockable one, there is a
* risk of selecting a parameter common with other group, albeit the probability is reduced and
* probably (I have not demonstrated it though and I am not sure), it leads to the right
* solution in one iteration.
*
*/
bool analyseBlockedConstraintDependentParameters(std::vector<int> &blockedGeoIds, std::vector<double *> &params_to_block) const;
bool analyseBlockedConstraintDependentParameters(std::vector<int>& blockedGeoIds,
std::vector<double*>& params_to_block) const;
/// utility function refactoring fixing the provided parameters and running a new diagnose
void fixParametersAndDiagnose(std::vector<double *> &params_to_block);
void fixParametersAndDiagnose(std::vector<double*>& params_to_block);
};
} //namespace Part
}// namespace Sketcher
#endif // SKETCHER_SKETCH_H
#endif// SKETCHER_SKETCH_H

View File

@@ -23,40 +23,37 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
#include <cmath>
# include <BRep_Tool.hxx>
# include <gp_Pnt.hxx>
# include <Precision.hxx>
# include <TopExp.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Shape.hxx>
# include <TopoDS_Vertex.hxx>
# include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <BRep_Tool.hxx>
#include <Precision.hxx>
#include <TopExp.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <gp_Pnt.hxx>
#endif
#include <App/Document.h>
#include <Base/Console.h>
#include "SketchAnalysis.h"
#include "GeometryFacade.h"
#include "SketchAnalysis.h"
#include "SketchObject.h"
using namespace Sketcher;
SketchAnalysis::SketchAnalysis(Sketcher::SketchObject* Obj)
: sketch(Obj)
{
}
: sketch(Obj)
{}
SketchAnalysis::~SketchAnalysis()
{}
struct SketchAnalysis::VertexIds
{
}
struct SketchAnalysis::VertexIds {
Base::Vector3d v;
int GeoId;
Sketcher::PointPos PosId;
@@ -64,98 +61,108 @@ struct SketchAnalysis::VertexIds {
struct SketchAnalysis::Vertex_Less
{
explicit Vertex_Less(double tolerance) : tolerance(tolerance){}
bool operator()(const VertexIds& x,
const VertexIds& y) const
explicit Vertex_Less(double tolerance)
: tolerance(tolerance)
{}
bool operator()(const VertexIds& x, const VertexIds& y) const
{
if (fabs (x.v.x - y.v.x) > tolerance)
if (fabs(x.v.x - y.v.x) > tolerance)
return x.v.x < y.v.x;
if (fabs (x.v.y - y.v.y) > tolerance)
if (fabs(x.v.y - y.v.y) > tolerance)
return x.v.y < y.v.y;
if (fabs (x.v.z - y.v.z) > tolerance)
if (fabs(x.v.z - y.v.z) > tolerance)
return x.v.z < y.v.z;
return false; // points are considered to be equal
return false;// points are considered to be equal
}
private:
double tolerance;
};
struct SketchAnalysis::VertexID_Less
{
bool operator()(const VertexIds& x,
const VertexIds& y) const
bool operator()(const VertexIds& x, const VertexIds& y) const
{
return (x.GeoId < y.GeoId || ((x.GeoId == y.GeoId) && (x.PosId < y. PosId)));
return (x.GeoId < y.GeoId || ((x.GeoId == y.GeoId) && (x.PosId < y.PosId)));
}
};
struct SketchAnalysis::Vertex_EqualTo
{
explicit Vertex_EqualTo(double tolerance) : tolerance(tolerance){}
bool operator()(const VertexIds& x,
const VertexIds& y) const
explicit Vertex_EqualTo(double tolerance)
: tolerance(tolerance)
{}
bool operator()(const VertexIds& x, const VertexIds& y) const
{
if (fabs (x.v.x - y.v.x) <= tolerance) {
if (fabs (x.v.y - y.v.y) <= tolerance) {
if (fabs (x.v.z - y.v.z) <= tolerance) {
if (fabs(x.v.x - y.v.x) <= tolerance) {
if (fabs(x.v.y - y.v.y) <= tolerance) {
if (fabs(x.v.z - y.v.z) <= tolerance) {
return true;
}
}
}
return false;
}
private:
double tolerance;
};
struct SketchAnalysis::EdgeIds {
struct SketchAnalysis::EdgeIds
{
double l;
int GeoId;
};
struct SketchAnalysis::Edge_Less
{
explicit Edge_Less(double tolerance) : tolerance(tolerance){}
bool operator()(const EdgeIds& x,
const EdgeIds& y) const
{
if (fabs (x.l - y.l) > tolerance)
return x.l < y.l;
return false; // points are considered to be equal
}
explicit Edge_Less(double tolerance)
: tolerance(tolerance)
{}
bool operator()(const EdgeIds& x, const EdgeIds& y) const
{
if (fabs(x.l - y.l) > tolerance)
return x.l < y.l;
return false;// points are considered to be equal
}
private:
double tolerance;
};
struct SketchAnalysis::Edge_EqualTo
{
explicit Edge_EqualTo(double tolerance) : tolerance(tolerance){}
bool operator()(const EdgeIds& x,
const EdgeIds& y) const
{
if (fabs (x.l - y.l) <= tolerance) {
return true;
}
return false;
}
explicit Edge_EqualTo(double tolerance)
: tolerance(tolerance)
{}
bool operator()(const EdgeIds& x, const EdgeIds& y) const
{
if (fabs(x.l - y.l) <= tolerance) {
return true;
}
return false;
}
private:
double tolerance;
};
int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool includeconstruction /*=true*/)
int SketchAnalysis::detectMissingPointOnPointConstraints(double precision,
bool includeconstruction /*=true*/)
{
std::vector<VertexIds> vertexIds; // Holds a list of all vertices in the sketch
std::vector<VertexIds> vertexIds;// Holds a list of all vertices in the sketch
// Build the list of sketch vertices
const std::vector<Part::Geometry *>& geom = sketch->getInternalGeometry();
for (std::size_t i=0; i<geom.size(); i++) {
const std::vector<Part::Geometry*>& geom = sketch->getInternalGeometry();
for (std::size_t i = 0; i < geom.size(); i++) {
auto gf = GeometryFacade::getFacade(geom[i]);
if(gf->getConstruction() && !includeconstruction)
if (gf->getConstruction() && !includeconstruction)
continue;
if (gf->getGeometry()->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *segm = static_cast<const Part::GeomLineSegment*>(gf->getGeometry());
const Part::GeomLineSegment* segm =
static_cast<const Part::GeomLineSegment*>(gf->getGeometry());
VertexIds id;
id.GeoId = (int)i;
id.PosId = Sketcher::PointPos::start;
@@ -167,7 +174,8 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
vertexIds.push_back(id);
}
else if (gf->getGeometry()->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *segm = static_cast<const Part::GeomArcOfCircle*>(gf->getGeometry());
const Part::GeomArcOfCircle* segm =
static_cast<const Part::GeomArcOfCircle*>(gf->getGeometry());
VertexIds id;
id.GeoId = (int)i;
id.PosId = Sketcher::PointPos::start;
@@ -179,7 +187,8 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
vertexIds.push_back(id);
}
else if (gf->getGeometry()->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
const Part::GeomArcOfEllipse *segm = static_cast<const Part::GeomArcOfEllipse*>(gf->getGeometry());
const Part::GeomArcOfEllipse* segm =
static_cast<const Part::GeomArcOfEllipse*>(gf->getGeometry());
VertexIds id;
id.GeoId = (int)i;
id.PosId = Sketcher::PointPos::start;
@@ -191,7 +200,8 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
vertexIds.push_back(id);
}
else if (gf->getGeometry()->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) {
const Part::GeomArcOfHyperbola *segm = static_cast<const Part::GeomArcOfHyperbola*>(gf->getGeometry());
const Part::GeomArcOfHyperbola* segm =
static_cast<const Part::GeomArcOfHyperbola*>(gf->getGeometry());
VertexIds id;
id.GeoId = (int)i;
id.PosId = Sketcher::PointPos::start;
@@ -203,7 +213,8 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
vertexIds.push_back(id);
}
else if (gf->getGeometry()->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) {
const Part::GeomArcOfParabola *segm = static_cast<const Part::GeomArcOfParabola*>(gf->getGeometry());
const Part::GeomArcOfParabola* segm =
static_cast<const Part::GeomArcOfParabola*>(gf->getGeometry());
VertexIds id;
id.GeoId = (int)i;
id.PosId = Sketcher::PointPos::start;
@@ -215,7 +226,8 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
vertexIds.push_back(id);
}
else if (gf->getGeometry()->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) {
const Part::GeomBSplineCurve *segm = static_cast<const Part::GeomBSplineCurve*>(gf->getGeometry());
const Part::GeomBSplineCurve* segm =
static_cast<const Part::GeomBSplineCurve*>(gf->getGeometry());
VertexIds id;
id.GeoId = (int)i;
id.PosId = Sketcher::PointPos::start;
@@ -229,22 +241,22 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
// TODO take into account single vertices ?
}
std::sort(vertexIds.begin(), vertexIds.end(), Vertex_Less(precision)); // Sort points in geographic order
// Sort points in geographic order
std::sort(vertexIds.begin(), vertexIds.end(), Vertex_Less(precision));
// Build a list of all coincidence in the sketch
std::vector<Sketcher::Constraint*> coincidences = sketch->Constraints.getValues();
for (auto &constraint:sketch->Constraints.getValues()) {
if (constraint->Type == Sketcher::Coincident ||
constraint->Type == Sketcher::Tangent ||
constraint->Type == Sketcher::Perpendicular) {
for (auto& constraint : sketch->Constraints.getValues()) {
if (constraint->Type == Sketcher::Coincident || constraint->Type == Sketcher::Tangent
|| constraint->Type == Sketcher::Perpendicular) {
coincidences.push_back(constraint);
}
// TODO optimizing by removing constraints not applying on vertices ?
}
std::list<ConstraintIds> missingCoincidences; //Holds the list of missing coincidences
std::list<ConstraintIds> missingCoincidences;// Holds the list of missing coincidences
std::vector<VertexIds>::iterator vt = vertexIds.begin();
Vertex_EqualTo pred(precision);
@@ -254,13 +266,14 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
while (vt < vertexIds.end()) {
// Seeking for adjacent group of vertices
vt = std::adjacent_find(vt, vertexIds.end(), pred);
if (vt < vertexIds.end()) { // If one found
if (vt < vertexIds.end()) {// If one found
std::vector<VertexIds>::iterator vn;
std::set<VertexIds, VertexID_Less> vertexGrp; // Holds a single group of adjacent vertices
// Holds a single group of adjacent vertices
std::set<VertexIds, VertexID_Less> vertexGrp;
// Extract the group of adjacent vertices
vertexGrp.insert(*vt);
for (vn = vt+1; vn < vertexIds.end(); ++vn) {
if (pred(*vt,*vn)) {
for (vn = vt + 1; vn < vertexIds.end(); ++vn) {
if (pred(*vt, *vn)) {
vertexGrp.insert(*vn);
}
else {
@@ -268,10 +281,12 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
}
}
std::vector<std::set<VertexIds, VertexID_Less>> coincVertexGrps; // Holds groups of coincident vertices
// Holds groups of coincident vertices
std::vector<std::set<VertexIds, VertexID_Less>> coincVertexGrps;
// Decompose the group of adjacent vertices into groups of coincident vertices
for (auto &coincidence:coincidences) { // Going through existent coincidences
// Going through existent coincidences
for (auto& coincidence : coincidences) {
VertexIds v1, v2;
v1.GeoId = coincidence->First;
v1.PosId = coincidence->FirstPos;
@@ -285,9 +300,9 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
// Maybe if both empty, they already have been extracted by other coincidences
// We have to check in existing coincident groups and eventually merge
if (nv1.empty() && nv2.empty()) {
std::set<VertexIds, VertexID_Less> *tempGrp = nullptr;
std::set<VertexIds, VertexID_Less>* tempGrp = nullptr;
for (auto it = coincVertexGrps.begin(); it < coincVertexGrps.end(); ++it) {
if ( (it->find(v1) != it->end()) || (it->find(v2) != it->end()) ) {
if ((it->find(v1) != it->end()) || (it->find(v2) != it->end())) {
if (!tempGrp) {
tempGrp = &*it;
}
@@ -301,17 +316,21 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
continue;
}
// Look if one of the constrained vertices is already in a group of coincident vertices
for (std::set<VertexIds, VertexID_Less> &grp:coincVertexGrps) {
if ( (grp.find(v1) != grp.end()) || (grp.find(v2) != grp.end()) ) {
// Look if one of the constrained vertices is already in a group of coincident
// vertices
for (std::set<VertexIds, VertexID_Less>& grp : coincVertexGrps) {
if ((grp.find(v1) != grp.end()) || (grp.find(v2) != grp.end())) {
// If yes add them to the existing group
if (!nv1.empty()) grp.insert(nv1.value());
if (!nv2.empty()) grp.insert(nv2.value());
if (!nv1.empty())
grp.insert(nv1.value());
if (!nv2.empty())
grp.insert(nv2.value());
continue;
}
}
if (nv1.empty() || nv2.empty()) continue;
if (nv1.empty() || nv2.empty())
continue;
// If no, create a new group of coincident vertices
std::set<VertexIds, VertexID_Less> newGrp;
@@ -320,26 +339,26 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
coincVertexGrps.push_back(newGrp);
}
// If there are remaining vertices in the adjacent group (not in any existing constraint)
// add them as being each a separate coincident group
for (auto &lonept: vertexGrp) {
// If there are remaining vertices in the adjacent group (not in any existing
// constraint) add them as being each a separate coincident group
for (auto& lonept : vertexGrp) {
std::set<VertexIds, VertexID_Less> newGrp;
newGrp.insert(lonept);
coincVertexGrps.push_back(newGrp);
}
// If there is more than 1 coincident group into adjacent group, constraint(s) is(are) missing
// Virtually generate the missing constraint(s)
// If there is more than 1 coincident group into adjacent group, constraint(s) is(are)
// missing Virtually generate the missing constraint(s)
if (coincVertexGrps.size() > 1) {
std::vector<std::set<VertexIds, VertexID_Less>>::iterator vn;
// Starting from the 2nd coincident group, generate a constraint between
// this group first vertex, and previous group first vertex
for (vn = coincVertexGrps.begin()+1; vn < coincVertexGrps.end(); ++vn) {
for (vn = coincVertexGrps.begin() + 1; vn < coincVertexGrps.end(); ++vn) {
ConstraintIds id;
id.Type = Coincident; // default point on point restriction
id.v = (vn-1)->begin()->v;
id.First = (vn-1)->begin()->GeoId;
id.FirstPos = (vn-1)->begin()->PosId;
id.Type = Coincident;// default point on point restriction
id.v = (vn - 1)->begin()->v;
id.First = (vn - 1)->begin()->GeoId;
id.FirstPos = (vn - 1)->begin()->PosId;
id.Second = vn->begin()->GeoId;
id.SecondPos = vn->begin()->PosId;
missingCoincidences.push_back(id);
@@ -354,7 +373,7 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
this->vertexConstraints.clear();
this->vertexConstraints.reserve(missingCoincidences.size());
for (auto &coincidence:missingCoincidences) {
for (auto& coincidence : missingCoincidences) {
this->vertexConstraints.push_back(coincidence);
}
@@ -364,28 +383,31 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool
void SketchAnalysis::analyseMissingPointOnPointCoincident(double angleprecision)
{
for(auto & vc : vertexConstraints) {
for (auto& vc : vertexConstraints) {
auto geo1 = sketch->getGeometry(vc.First);
auto geo2 = sketch->getGeometry(vc.Second);
// tangency point-on-point
const Part::GeomCurve * curve1 = dynamic_cast<const Part::GeomCurve *>(geo1);
const Part::GeomCurve * curve2 = dynamic_cast<const Part::GeomCurve *>(geo2);
const Part::GeomCurve* curve1 = dynamic_cast<const Part::GeomCurve*>(geo1);
const Part::GeomCurve* curve2 = dynamic_cast<const Part::GeomCurve*>(geo2);
if(curve1 && curve2) {
if (curve1 && curve2) {
if( geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId()
&& geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *segm1 = static_cast<const Part::GeomLineSegment*>(geo1);
const Part::GeomLineSegment *segm2 = static_cast<const Part::GeomLineSegment*>(geo2);
const Part::GeomLineSegment* segm1 =
static_cast<const Part::GeomLineSegment*>(geo1);
const Part::GeomLineSegment* segm2 =
static_cast<const Part::GeomLineSegment*>(geo2);
Base::Vector3d dir1 = segm1->getEndPoint() - segm1->getStartPoint();
Base::Vector3d dir2 = segm2->getEndPoint() - segm2->getStartPoint();
if( (checkVertical(dir1,angleprecision) || checkHorizontal(dir1,angleprecision)) &&
(checkVertical(dir2,angleprecision) || checkHorizontal(dir2,angleprecision)) ) {
if ((checkVertical(dir1, angleprecision) || checkHorizontal(dir1, angleprecision))
&& (checkVertical(dir2, angleprecision)
|| checkHorizontal(dir2, angleprecision))) {
// this is a job for horizontal/vertical constraints alone
continue;
}
@@ -394,26 +416,24 @@ void SketchAnalysis::analyseMissingPointOnPointCoincident(double angleprecision)
try {
double u1, u2;
curve1->closestParameter(vc.v,u1);
curve2->closestParameter(vc.v,u2);
curve1->closestParameter(vc.v, u1);
curve2->closestParameter(vc.v, u2);
Base::Vector3d tgv1 = curve1->firstDerivativeAtParameter(u1).Normalize();
Base::Vector3d tgv2 = curve2->firstDerivativeAtParameter(u2).Normalize();
if(fabs(tgv1*tgv2)>fabs(cos(angleprecision))) {
if (fabs(tgv1 * tgv2) > fabs(cos(angleprecision))) {
vc.Type = Sketcher::Tangent;
}
else if(fabs(tgv1*tgv2)<fabs(cos(M_PI/2 - angleprecision))) {
else if (fabs(tgv1 * tgv2) < fabs(cos(M_PI / 2 - angleprecision))) {
vc.Type = Sketcher::Perpendicular;
}
}
catch(Base::Exception &) {
Base::Console().Warning("Point-On-Point Coincidence analysis: unable to obtain derivative. Detection ignored.\n");
catch (Base::Exception&) {
Base::Console().Warning("Point-On-Point Coincidence analysis: unable to obtain "
"derivative. Detection ignored.\n");
continue;
}
}
}
}
@@ -424,7 +444,9 @@ void SketchAnalysis::makeMissingPointOnPointCoincident(bool onebyone)
int status, dofs;
std::vector<Sketcher::Constraint*> constr;
for (std::vector<Sketcher::ConstraintIds>::iterator it = vertexConstraints.begin(); it != vertexConstraints.end(); ++it) {
for (std::vector<Sketcher::ConstraintIds>::iterator it = vertexConstraints.begin();
it != vertexConstraints.end();
++it) {
Sketcher::Constraint* c = new Sketcher::Constraint();
c->Type = it->Type;
c->First = it->First;
@@ -432,21 +454,24 @@ void SketchAnalysis::makeMissingPointOnPointCoincident(bool onebyone)
c->FirstPos = it->FirstPos;
c->SecondPos = it->SecondPos;
if(onebyone) {
if (onebyone) {
// addConstraint() creates a clone
sketch->addConstraint(c);
delete c;
solvesketch(status,dofs,true);
solvesketch(status, dofs, true);
if(status == -2) { //redundant constraints
if (status == -2) {// redundant constraints
sketch->autoRemoveRedundants(false);
solvesketch(status,dofs,false);
solvesketch(status, dofs, false);
}
if(status) {
THROWMT(Base::RuntimeError, QT_TRANSLATE_NOOP("Exceptions", "Autoconstrain error: Unsolvable sketch while applying coincident constraints."));
if (status) {
THROWMT(Base::RuntimeError,
QT_TRANSLATE_NOOP("Exceptions",
"Autoconstrain error: Unsolvable sketch while applying "
"coincident constraints."));
}
}
else {
@@ -454,27 +479,28 @@ void SketchAnalysis::makeMissingPointOnPointCoincident(bool onebyone)
}
}
if(!onebyone)
if (!onebyone)
sketch->addConstraints(constr);
vertexConstraints.clear();
for (std::vector<Sketcher::Constraint*>::iterator it = constr.begin(); it != constr.end(); ++it) {
for (std::vector<Sketcher::Constraint*>::iterator it = constr.begin(); it != constr.end();
++it) {
delete *it;
}
}
int SketchAnalysis::detectMissingVerticalHorizontalConstraints(double angleprecision)
{
const std::vector<Part::Geometry *>& geom = sketch->getInternalGeometry();
const std::vector<Part::Geometry*>& geom = sketch->getInternalGeometry();
verthorizConstraints.clear();
for (std::size_t i=0; i<geom.size(); i++) {
for (std::size_t i = 0; i < geom.size(); i++) {
Part::Geometry* g = geom[i];
if (g->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *segm = static_cast<const Part::GeomLineSegment*>(g);
const Part::GeomLineSegment* segm = static_cast<const Part::GeomLineSegment*>(g);
Base::Vector3d dir = segm->getEndPoint() - segm->getStartPoint();
@@ -486,11 +512,11 @@ int SketchAnalysis::detectMissingVerticalHorizontalConstraints(double anglepreci
id.Second = GeoEnum::GeoUndef;
id.SecondPos = Sketcher::PointPos::none;
if( checkVertical(dir, angleprecision) ) {
if (checkVertical(dir, angleprecision)) {
id.Type = Sketcher::Vertical;
verthorizConstraints.push_back(id);
}
else if (checkHorizontal(dir, angleprecision) ) {
else if (checkHorizontal(dir, angleprecision)) {
id.Type = Sketcher::Horizontal;
verthorizConstraints.push_back(id);
}
@@ -505,7 +531,9 @@ void SketchAnalysis::makeMissingVerticalHorizontal(bool onebyone)
int status, dofs;
std::vector<Sketcher::Constraint*> constr;
for (std::vector<Sketcher::ConstraintIds>::iterator it = verthorizConstraints.begin(); it != verthorizConstraints.end(); ++it) {
for (std::vector<Sketcher::ConstraintIds>::iterator it = verthorizConstraints.begin();
it != verthorizConstraints.end();
++it) {
Sketcher::Constraint* c = new Sketcher::Constraint();
c->Type = it->Type;
c->First = it->First;
@@ -513,21 +541,24 @@ void SketchAnalysis::makeMissingVerticalHorizontal(bool onebyone)
c->FirstPos = it->FirstPos;
c->SecondPos = it->SecondPos;
if(onebyone) {
if (onebyone) {
// addConstraint() creates a clone
sketch->addConstraint(c);
delete c;
solvesketch(status,dofs,true);
solvesketch(status, dofs, true);
if(status == -2) { //redundant constraints
if (status == -2) {// redundant constraints
sketch->autoRemoveRedundants(false);
solvesketch(status,dofs,false);
solvesketch(status, dofs, false);
}
if(status) {
THROWMT(Base::RuntimeError, QT_TRANSLATE_NOOP("Exceptions", "Autoconstrain error: Unsolvable sketch while applying vertical/horizontal constraints."));
if (status) {
THROWMT(Base::RuntimeError,
QT_TRANSLATE_NOOP("Exceptions",
"Autoconstrain error: Unsolvable sketch while applying "
"vertical/horizontal constraints."));
}
}
else {
@@ -535,24 +566,25 @@ void SketchAnalysis::makeMissingVerticalHorizontal(bool onebyone)
}
}
if(!onebyone)
if (!onebyone)
sketch->addConstraints(constr);
verthorizConstraints.clear();
for (std::vector<Sketcher::Constraint*>::iterator it = constr.begin(); it != constr.end(); ++it) {
for (std::vector<Sketcher::Constraint*>::iterator it = constr.begin(); it != constr.end();
++it) {
delete *it;
}
}
bool SketchAnalysis::checkVertical(Base::Vector3d dir, double angleprecision)
{
return (dir.x == 0. && dir.y != 0.) || ( fabs(dir.y/dir.x) > tan(M_PI/2 - angleprecision));
return (dir.x == 0. && dir.y != 0.) || (fabs(dir.y / dir.x) > tan(M_PI / 2 - angleprecision));
}
bool SketchAnalysis::checkHorizontal(Base::Vector3d dir, double angleprecision)
{
return (dir.y == 0. && dir.x != 0.) || ( fabs(dir.x/dir.y) > (1/tan(angleprecision)));
return (dir.y == 0. && dir.x != 0.) || (fabs(dir.x / dir.y) > (1 / tan(angleprecision)));
}
int SketchAnalysis::detectMissingEqualityConstraints(double precision)
@@ -560,26 +592,26 @@ int SketchAnalysis::detectMissingEqualityConstraints(double precision)
std::vector<EdgeIds> lineedgeIds;
std::vector<EdgeIds> radiusedgeIds;
const std::vector<Part::Geometry *>& geom = sketch->getInternalGeometry();
for (std::size_t i=0; i<geom.size(); i++) {
const std::vector<Part::Geometry*>& geom = sketch->getInternalGeometry();
for (std::size_t i = 0; i < geom.size(); i++) {
Part::Geometry* g = geom[i];
if (g->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *segm = static_cast<const Part::GeomLineSegment*>(g);
const Part::GeomLineSegment* segm = static_cast<const Part::GeomLineSegment*>(g);
EdgeIds id;
id.GeoId = (int)i;
id.l = (segm->getEndPoint()-segm->getStartPoint()).Length();
id.l = (segm->getEndPoint() - segm->getStartPoint()).Length();
lineedgeIds.push_back(id);
}
else if (g->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *segm = static_cast<const Part::GeomArcOfCircle*>(g);
const Part::GeomArcOfCircle* segm = static_cast<const Part::GeomArcOfCircle*>(g);
EdgeIds id;
id.GeoId = (int)i;
id.l = segm->getRadius();
radiusedgeIds.push_back(id);
}
else if (g->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *segm = static_cast<const Part::GeomCircle*>(g);
const Part::GeomCircle* segm = static_cast<const Part::GeomCircle*>(g);
EdgeIds id;
id.GeoId = (int)i;
id.l = segm->getRadius();
@@ -598,8 +630,8 @@ int SketchAnalysis::detectMissingEqualityConstraints(double precision)
vt = std::adjacent_find(vt, lineedgeIds.end(), pred);
if (vt < lineedgeIds.end()) {
std::vector<EdgeIds>::iterator vn;
for (vn = vt+1; vn != lineedgeIds.end(); ++vn) {
if (pred(*vt,*vn)) {
for (vn = vt + 1; vn != lineedgeIds.end(); ++vn) {
if (pred(*vt, *vn)) {
ConstraintIds id;
id.Type = Equal;
id.v.x = vt->l;
@@ -628,8 +660,8 @@ int SketchAnalysis::detectMissingEqualityConstraints(double precision)
vt = std::adjacent_find(vt, radiusedgeIds.end(), pred);
if (vt < radiusedgeIds.end()) {
std::vector<EdgeIds>::iterator vn;
for (vn = vt+1; vn != radiusedgeIds.end(); ++vn) {
if (pred(*vt,*vn)) {
for (vn = vt + 1; vn != radiusedgeIds.end(); ++vn) {
if (pred(*vt, *vn)) {
ConstraintIds id;
id.Type = Equal;
id.v.x = vt->l;
@@ -653,26 +685,25 @@ int SketchAnalysis::detectMissingEqualityConstraints(double precision)
// and check which of them is forcing two vertexes to be coincident.
// If there is none but two vertexes can be considered equal a coincident constraint is missing.
std::vector<Sketcher::Constraint*> constraint = sketch->Constraints.getValues();
for (std::vector<Sketcher::Constraint*>::iterator it = constraint.begin(); it != constraint.end(); ++it) {
for (std::vector<Sketcher::Constraint*>::iterator it = constraint.begin();
it != constraint.end();
++it) {
if ((*it)->Type == Sketcher::Equal) {
ConstraintIds id {
Base::Vector3d{},
(*it)->First,
(*it)->Second,
(*it)->FirstPos,
(*it)->SecondPos,
(*it)->Type
};
ConstraintIds id {Base::Vector3d {},
(*it)->First,
(*it)->Second,
(*it)->FirstPos,
(*it)->SecondPos,
(*it)->Type};
std::list<ConstraintIds>::iterator pos = std::find_if
(equallines.begin(), equallines.end(), Constraint_Equal(id));
std::list<ConstraintIds>::iterator pos =
std::find_if(equallines.begin(), equallines.end(), Constraint_Equal(id));
if (pos != equallines.end()) {
equallines.erase(pos);
}
pos = std::find_if
(equalradius.begin(), equalradius.end(), Constraint_Equal(id));
pos = std::find_if(equalradius.begin(), equalradius.end(), Constraint_Equal(id));
if (pos != equalradius.end()) {
equalradius.erase(pos);
@@ -690,7 +721,8 @@ int SketchAnalysis::detectMissingEqualityConstraints(double precision)
this->radiusequalityConstraints.clear();
this->radiusequalityConstraints.reserve(equalradius.size());
for (std::list<ConstraintIds>::iterator it = equalradius.begin(); it != equalradius.end(); ++it) {
for (std::list<ConstraintIds>::iterator it = equalradius.begin(); it != equalradius.end();
++it) {
this->radiusequalityConstraints.push_back(*it);
}
@@ -703,9 +735,12 @@ void SketchAnalysis::makeMissingEquality(bool onebyone)
std::vector<Sketcher::Constraint*> constr;
std::vector<Sketcher::ConstraintIds> equalities(lineequalityConstraints);
equalities.insert(equalities.end(),radiusequalityConstraints.begin(), radiusequalityConstraints.end());
equalities.insert(
equalities.end(), radiusequalityConstraints.begin(), radiusequalityConstraints.end());
for (std::vector<Sketcher::ConstraintIds>::iterator it = equalities.begin(); it != equalities.end(); ++it) {
for (std::vector<Sketcher::ConstraintIds>::iterator it = equalities.begin();
it != equalities.end();
++it) {
Sketcher::Constraint* c = new Sketcher::Constraint();
c->Type = it->Type;
c->First = it->First;
@@ -713,21 +748,24 @@ void SketchAnalysis::makeMissingEquality(bool onebyone)
c->FirstPos = it->FirstPos;
c->SecondPos = it->SecondPos;
if(onebyone) {
if (onebyone) {
// addConstraint() creates a clone
sketch->addConstraint(c);
delete c;
solvesketch(status,dofs,true);
solvesketch(status, dofs, true);
if(status == -2) { //redundant constraints
if (status == -2) {// redundant constraints
sketch->autoRemoveRedundants(false);
solvesketch(status,dofs,false);
solvesketch(status, dofs, false);
}
if(status) {
THROWMT(Base::RuntimeError, QT_TRANSLATE_NOOP("Exceptions", "Autoconstrain error: Unsolvable sketch while applying equality constraints."));
if (status) {
THROWMT(Base::RuntimeError,
QT_TRANSLATE_NOOP("Exceptions",
"Autoconstrain error: Unsolvable sketch while applying "
"equality constraints."));
}
}
else {
@@ -735,39 +773,41 @@ void SketchAnalysis::makeMissingEquality(bool onebyone)
}
}
if(!onebyone)
if (!onebyone)
sketch->addConstraints(constr);
lineequalityConstraints.clear();
radiusequalityConstraints.clear();
for (std::vector<Sketcher::Constraint*>::iterator it = constr.begin(); it != constr.end(); ++it) {
for (std::vector<Sketcher::Constraint*>::iterator it = constr.begin(); it != constr.end();
++it) {
delete *it;
}
}
void SketchAnalysis::solvesketch(int &status, int &dofs, bool updategeo)
void SketchAnalysis::solvesketch(int& status, int& dofs, bool updategeo)
{
status = sketch->solve(updategeo);
if(updategeo)
if (updategeo)
dofs = sketch->setUpSketch();
else
dofs = sketch->getLastDoF();
if (sketch->getLastHasRedundancies()) { // redundant constraints
if (sketch->getLastHasRedundancies()) {// redundant constraints
status = -2;
}
if (dofs < 0) { // over-constrained sketch
if (dofs < 0) {// over-constrained sketch
status = -4;
}
else if (sketch->getLastHasConflicts()) { // conflicting constraints
else if (sketch->getLastHasConflicts()) {// conflicting constraints
status = -3;
}
}
int SketchAnalysis::autoconstraint(double precision, double angleprecision, bool includeconstruction)
int SketchAnalysis::autoconstraint(double precision, double angleprecision,
bool includeconstruction)
{
App::Document* doc = sketch->getDocument();
doc->openTransaction("delete all constraints");
@@ -778,30 +818,38 @@ int SketchAnalysis::autoconstraint(double precision, double angleprecision, bool
int status, dofs;
solvesketch(status,dofs,true);
solvesketch(status, dofs, true);
if(status) {// it should not be possible at this moment as we start from a clean situation
THROWMT(Base::RuntimeError, QT_TRANSLATE_NOOP("Exceptions", "Autoconstrain error: Unsolvable sketch without constraints."));
if (status) {// it should not be possible at this moment as we start from a clean situation
THROWMT(Base::RuntimeError,
QT_TRANSLATE_NOOP("Exceptions",
"Autoconstrain error: Unsolvable sketch without constraints."));
}
// STAGE 1: Vertical/Horizontal Line Segments
int nhv = detectMissingVerticalHorizontalConstraints(angleprecision);
// STAGE 2: Point-on-Point constraint (Coincidents, endpoint perp, endpoint tangency)
// Note: We do not apply the vertical/horizontal constraints before calculating the pointonpoint constraints
// Note: We do not apply the vertical/horizontal constraints before calculating the pointonpoint
// constraints
// as the solver may move the geometry in the meantime and prevent correct detection
int nc = detectMissingPointOnPointConstraints(precision, includeconstruction);
if (nc > 0) // STAGE 2a: Classify point-on-point into coincidents, endpoint perp, endpoint tangency
if (nc
> 0)// STAGE 2a: Classify point-on-point into coincidents, endpoint perp, endpoint tangency
analyseMissingPointOnPointCoincident(angleprecision);
// STAGE 3: Equality constraint detection
int ne = detectMissingEqualityConstraints(precision);
Base::Console().Log("Constraints: Vertical/Horizontal: %d found. Point-on-point: %d. Equality: %d\n", nhv, nc, ne);
Base::Console().Log(
"Constraints: Vertical/Horizontal: %d found. Point-on-point: %d. Equality: %d\n",
nhv,
nc,
ne);
// Applying STAGE 1, if any
if (nhv >0 ) {
if (nhv > 0) {
App::Document* doc = sketch->getDocument();
doc->openTransaction("add vertical/horizontal constraints");
@@ -810,20 +858,23 @@ int SketchAnalysis::autoconstraint(double precision, double angleprecision, bool
// finish the transaction and update
doc->commitTransaction();
solvesketch(status,dofs,true);
solvesketch(status, dofs, true);
if(status == -2) { // redundants
if (status == -2) {// redundants
sketch->autoRemoveRedundants(false);
solvesketch(status,dofs,false);
solvesketch(status, dofs, false);
}
if(status) {
THROWMT(Base::RuntimeError, QT_TRANSLATE_NOOP("Exceptions", "Autoconstrain error: Unsolvable sketch after applying horizontal and vertical constraints."));
if (status) {
THROWMT(Base::RuntimeError,
QT_TRANSLATE_NOOP("Exceptions",
"Autoconstrain error: Unsolvable sketch after applying "
"horizontal and vertical constraints."));
}
}
// Applying STAGE 2
if(nc > 0) {
if (nc > 0) {
App::Document* doc = sketch->getDocument();
doc->openTransaction("add coincident constraint");
@@ -832,27 +883,30 @@ int SketchAnalysis::autoconstraint(double precision, double angleprecision, bool
// finish the transaction and update
doc->commitTransaction();
solvesketch(status,dofs,true);
solvesketch(status, dofs, true);
if(status == -2) { // redundants
if (status == -2) {// redundants
sketch->autoRemoveRedundants(false);
solvesketch(status,dofs,false);
solvesketch(status, dofs, false);
}
if(status) {
THROWMT(Base::RuntimeError, QT_TRANSLATE_NOOP("Exceptions", "Autoconstrain error: Unsolvable sketch after applying point-on-point constraints."));
if (status) {
THROWMT(Base::RuntimeError,
QT_TRANSLATE_NOOP("Exceptions",
"Autoconstrain error: Unsolvable sketch after applying "
"point-on-point constraints."));
}
}
// Applying STAGE 3
if(ne > 0) {
if (ne > 0) {
App::Document* doc = sketch->getDocument();
doc->openTransaction("add equality constraints");
try {
makeMissingEquality();
}
catch(Base::RuntimeError &) {
catch (Base::RuntimeError&) {
doc->abortTransaction();
throw;
}
@@ -860,15 +914,19 @@ int SketchAnalysis::autoconstraint(double precision, double angleprecision, bool
// finish the transaction and update
doc->commitTransaction();
solvesketch(status,dofs,true);
solvesketch(status, dofs, true);
if(status == -2) { // redundants
if (status == -2) {// redundants
sketch->autoRemoveRedundants(false);
solvesketch(status,dofs,false);
solvesketch(status, dofs, false);
}
if(status) {
THROWMT(Base::RuntimeError, QT_TRANSLATE_NOOP("Exceptions", "Autoconstrain error: Unsolvable sketch after applying equality constraints."));
if (status) {
THROWMT(
Base::RuntimeError,
QT_TRANSLATE_NOOP(
"Exceptions",
"Autoconstrain error: Unsolvable sketch after applying equality constraints."));
}
}
@@ -889,13 +947,13 @@ std::vector<Base::Vector3d> SketchAnalysis::getOpenVertices() const
// build up map vertex->edge
TopTools_IndexedDataMapOfShapeListOfShape vertex2Edge;
TopExp::MapShapesAndAncestors(shape, TopAbs_VERTEX, TopAbs_EDGE, vertex2Edge);
for (int i=1; i<= vertex2Edge.Extent(); ++i) {
for (int i = 1; i <= vertex2Edge.Extent(); ++i) {
const TopTools_ListOfShape& los = vertex2Edge.FindFromIndex(i);
if (los.Extent() != 2) {
const TopoDS_Vertex& vertex = TopoDS::Vertex(vertex2Edge.FindKey(i));
gp_Pnt pnt = BRep_Tool::Pnt(vertex);
Base::Vector3d pos;
invPlm.multVec(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()),pos);
invPlm.multVec(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()), pos);
points.push_back(pos);
}
}
@@ -906,8 +964,8 @@ std::vector<Base::Vector3d> SketchAnalysis::getOpenVertices() const
int SketchAnalysis::detectDegeneratedGeometries(double tolerance)
{
int countDegenerated = 0;
const std::vector<Part::Geometry *>& geom = sketch->getInternalGeometry();
for (std::size_t i=0; i<geom.size(); i++) {
const std::vector<Part::Geometry*>& geom = sketch->getInternalGeometry();
for (std::size_t i = 0; i < geom.size(); i++) {
auto gf = GeometryFacade::getFacade(geom[i]);
if (gf->getConstruction())
@@ -927,9 +985,9 @@ int SketchAnalysis::detectDegeneratedGeometries(double tolerance)
int SketchAnalysis::removeDegeneratedGeometries(double tolerance)
{
std::set<int> delInternalGeometries;
const std::vector<Part::Geometry *>& geom = sketch->getInternalGeometry();
for (std::size_t i=0; i<geom.size(); i++) {
auto gf = GeometryFacade::getFacade(geom[i]);
const std::vector<Part::Geometry*>& geom = sketch->getInternalGeometry();
for (std::size_t i = 0; i < geom.size(); i++) {
auto gf = GeometryFacade::getFacade(geom[i]);
if (gf->getConstruction())
continue;

View File

@@ -32,76 +32,110 @@
#include "Analyse.h"
namespace Sketcher {
namespace Sketcher
{
class SketchObject;
class SketcherExport SketchAnalysis
{
public:
/// Creates an instance of the SketchAnalysis object, taking as parameter a pointer to an SketchObject.
/// Creates an instance of the SketchAnalysis object, taking as parameter a pointer to an
/// SketchObject.
///
/// There is a first type of routines, simple routines, which work in the following order:
/// Detect - (Analyse) - [Get] - [Set] - Make
///
/// The Detect step just identifies possible missing constraints.
///
/// The Analyse, which is not available for all the routines, operates in detected constraints of the same routine, to
/// look for alternatives. For example, a general pointonpoint detection leads to a search for coincident constraints, which
/// can be later run via Analyse if it is intended to convert endpoint coincidence to endpoint perpendicular and tangent constraints.
/// The Analyse, which is not available for all the routines, operates in detected constraints
/// of the same routine, to look for alternatives. For example, a general pointonpoint detection
/// leads to a search for coincident constraints, which can be later run via Analyse if it is
/// intended to convert endpoint coincidence to endpoint perpendicular and tangent constraints.
///
/// The Get retrieves the result of the analysis as a vector of ConstraintIds, indicating the suggested constraints. This step is intended
/// for enabling the user to check the result of the analysis, rather than applying it. If only applying is intended, this step is not necessary
/// as the Make will operate on the result of the Detect - Analyse directly.
/// The Get retrieves the result of the analysis as a vector of ConstraintIds, indicating the
/// suggested constraints. This step is intended for enabling the user to check the result of
/// the analysis, rather than applying it. If only applying is intended, this step is not
/// necessary as the Make will operate on the result of the Detect - Analyse directly.
///
/// The Set changes the detected result. It modifies the SketchAnalysis object. It only modifies the SketchObject as far as the SketchAnalysis is changed.
/// It does not apply any changes to the sketch. It is intended so as to enable the user to change the result that will be applied.
/// The Set changes the detected result. It modifies the SketchAnalysis object. It only modifies
/// the SketchObject as far as the SketchAnalysis is changed. It does not apply any changes to
/// the sketch. It is intended so as to enable the user to change the result that will be
/// applied.
///
/// Neither the Detect, nor the Analyse, nor the Get steps modify the Sketch geometry.
///
/// Make applies the constraints stored internally in the SketchAnalysis object.
///
/// A second type of routines, complex routines, are thought for running fully automatic and they Detect, Analyse and Make.
/// They may also apply a variety of constraint types.
/// A second type of routines, complex routines, are thought for running fully automatic and
/// they Detect, Analyse and Make. They may also apply a variety of constraint types.
///
/// A third type of routines do not relate to autoconstraining at all, and include validation methods for sketches.
explicit SketchAnalysis(Sketcher::SketchObject * Obj);
/// A third type of routines do not relate to autoconstraining at all, and include validation
/// methods for sketches.
explicit SketchAnalysis(Sketcher::SketchObject* Obj);
~SketchAnalysis();
// Simple routines (see constructor)
/// Point on Point constraint simple routine Detect step (see constructor)
/// Detect detects only coincident constraints, Analyse converts coincident to endpoint perpendicular/tangent where appropriate
int detectMissingPointOnPointConstraints(double precision = Precision::Confusion() * 1000, bool includeconstruction = true);
/// Detect detects only coincident constraints, Analyse converts coincident to endpoint
/// perpendicular/tangent where appropriate
int detectMissingPointOnPointConstraints(double precision = Precision::Confusion() * 1000,
bool includeconstruction = true);
/// Point on Point constraint simple routine Analyse step (see constructor)
void analyseMissingPointOnPointCoincident(double angleprecision = M_PI/8);
void analyseMissingPointOnPointCoincident(double angleprecision = M_PI / 8);
/// Point on Point constraint simple routine Get step (see constructor)
std::vector<ConstraintIds> &getMissingPointOnPointConstraints() {return vertexConstraints;}
std::vector<ConstraintIds>& getMissingPointOnPointConstraints()
{
return vertexConstraints;
}
/// Vertical/Horizontal constraints simple routine Set step (see constructor)
void setMissingPointOnPointConstraints(std::vector<ConstraintIds>& cl) {vertexConstraints = cl;}
void setMissingPointOnPointConstraints(std::vector<ConstraintIds>& cl)
{
vertexConstraints = cl;
}
/// Point on Point constraint simple routine Make step (see constructor)
/// if onebyone, then the sketch is solved after each individual constraint addition and any redundancy removed.
/// if onebyone, then the sketch is solved after each individual constraint addition and any
/// redundancy removed.
void makeMissingPointOnPointCoincident(bool onebyone = false);
/// Vertical/Horizontal constraints simple routine Detect step (see constructor)
int detectMissingVerticalHorizontalConstraints(double angleprecision = M_PI/8);
int detectMissingVerticalHorizontalConstraints(double angleprecision = M_PI / 8);
/// Vertical/Horizontal constraints simple routine Get step (see constructor)
std::vector<ConstraintIds> &getMissingVerticalHorizontalConstraints() {return verthorizConstraints;}
std::vector<ConstraintIds>& getMissingVerticalHorizontalConstraints()
{
return verthorizConstraints;
}
/// Vertical/Horizontal constraints simple routine Set step (see constructor)
void setMissingVerticalHorizontalConstraints(std::vector<ConstraintIds>& cl) {verthorizConstraints = cl;}
void setMissingVerticalHorizontalConstraints(std::vector<ConstraintIds>& cl)
{
verthorizConstraints = cl;
}
/// Vertical/Horizontal constraints simple routine Make step (see constructor)
void makeMissingVerticalHorizontal(bool onebyone = false);
/// Equality constraints simple routine Detect step (see constructor)
int detectMissingEqualityConstraints(double precision);
/// Equality constraints simple routine Get step for line segments (see constructor)
std::vector<ConstraintIds> &getMissingLineEqualityConstraints() {return lineequalityConstraints;}
std::vector<ConstraintIds>& getMissingLineEqualityConstraints()
{
return lineequalityConstraints;
}
/// Equality constraints simple routine Get step for radii (see constructor)
std::vector<ConstraintIds> &getMissingRadiusConstraints() {return radiusequalityConstraints;}
std::vector<ConstraintIds>& getMissingRadiusConstraints()
{
return radiusequalityConstraints;
}
/// Equality constraints simple routine Set step for line segments (see constructor)
void setMissingLineEqualityConstraints(std::vector<ConstraintIds>& cl) {lineequalityConstraints = cl;}
void setMissingLineEqualityConstraints(std::vector<ConstraintIds>& cl)
{
lineequalityConstraints = cl;
}
/// Equality constraints simple routine Set step for radii (see constructor)
void setMissingRadiusConstraints(std::vector<ConstraintIds>& cl) {radiusequalityConstraints = cl;}
void setMissingRadiusConstraints(std::vector<ConstraintIds>& cl)
{
radiusequalityConstraints = cl;
}
/// Equality constraints simple routine Make step (see constructor)
void makeMissingEquality(bool onebyone = true);
@@ -114,16 +148,20 @@ public:
/// Fully automated multi-constraint autoconstraining
///
/// It DELETES all the constraints currently present in the Sketcher. The reason is that it makes assumptions to avoid redundancies.
/// It DELETES all the constraints currently present in the Sketcher. The reason is that it
/// makes assumptions to avoid redundancies.
///
/// It applies coincidents - vertical/horizontal constraints and equality constraints.
int autoconstraint(double precision = Precision::Confusion() * 1000, double angleprecision = M_PI/8, bool includeconstruction = true);
int autoconstraint(double precision = Precision::Confusion() * 1000,
double angleprecision = M_PI / 8, bool includeconstruction = true);
// helper functions, which may be used by more complex methods, and/or called directly by user space (python) methods
// helper functions, which may be used by more complex methods, and/or called directly by user
// space (python) methods
/// solves the sketch and retrieves the error status, and the degrees of freedom.
/// It enables to solve updating the geometry (so moving the geometry to match the constraints) or preserving the geometry.
void solvesketch(int &status, int &dofs, bool updategeo);
/// It enables to solve updating the geometry (so moving the geometry to match the constraints)
/// or preserving the geometry.
void solvesketch(int& status, int& dofs, bool updategeo);
// third type of routines
std::vector<Base::Vector3d> getOpenVertices() const;
@@ -146,9 +184,8 @@ protected:
protected:
bool checkHorizontal(Base::Vector3d dir, double angleprecision);
bool checkVertical(Base::Vector3d dir, double angleprecision);
};
} //namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_SKETCHANALYSIS_H
#endif// SKETCHER_SKETCHANALYSIS_H

View File

@@ -32,62 +32,63 @@
using namespace Sketcher;
//---------- Geometry Extension
constexpr std::array<const char *, InternalType::NumInternalGeometryType> SketchGeometryExtension::internaltype2str;
constexpr std::array<const char *,GeometryMode::NumGeometryMode> SketchGeometryExtension::geometrymode2str;
constexpr std::array<const char*, InternalType::NumInternalGeometryType>
SketchGeometryExtension::internaltype2str;
constexpr std::array<const char*, GeometryMode::NumGeometryMode>
SketchGeometryExtension::geometrymode2str;
TYPESYSTEM_SOURCE(Sketcher::SketchGeometryExtension,Part::GeometryPersistenceExtension)
TYPESYSTEM_SOURCE(Sketcher::SketchGeometryExtension, Part::GeometryPersistenceExtension)
// scoped within the class, multithread ready
std::atomic<long> SketchGeometryExtension::_GeometryID;
SketchGeometryExtension::SketchGeometryExtension(): Id(++SketchGeometryExtension::_GeometryID),
InternalGeometryType(InternalType::None),
GeometryLayer(0)
{
SketchGeometryExtension::SketchGeometryExtension()
: Id(++SketchGeometryExtension::_GeometryID),
InternalGeometryType(InternalType::None),
GeometryLayer(0)
{}
}
SketchGeometryExtension::SketchGeometryExtension(long cid)
: Id(cid),
InternalGeometryType(InternalType::None),
GeometryLayer(0)
{}
SketchGeometryExtension::SketchGeometryExtension(long cid): Id(cid),
InternalGeometryType(InternalType::None),
GeometryLayer(0)
{
}
void SketchGeometryExtension::copyAttributes(Part::GeometryExtension * cpy) const
void SketchGeometryExtension::copyAttributes(Part::GeometryExtension* cpy) const
{
Part::GeometryPersistenceExtension::copyAttributes(cpy);
static_cast<SketchGeometryExtension *>(cpy)->Id = this->Id;
static_cast<SketchGeometryExtension *>(cpy)->InternalGeometryType = this->InternalGeometryType;
static_cast<SketchGeometryExtension *>(cpy)->GeometryModeFlags = this->GeometryModeFlags;
static_cast<SketchGeometryExtension *>(cpy)->GeometryLayer = this->GeometryLayer;
static_cast<SketchGeometryExtension*>(cpy)->Id = this->Id;
static_cast<SketchGeometryExtension*>(cpy)->InternalGeometryType = this->InternalGeometryType;
static_cast<SketchGeometryExtension*>(cpy)->GeometryModeFlags = this->GeometryModeFlags;
static_cast<SketchGeometryExtension*>(cpy)->GeometryLayer = this->GeometryLayer;
}
void SketchGeometryExtension::restoreAttributes(Base::XMLReader &reader)
void SketchGeometryExtension::restoreAttributes(Base::XMLReader& reader)
{
Part::GeometryPersistenceExtension::restoreAttributes(reader);
if(reader.hasAttribute("id"))
if (reader.hasAttribute("id"))
Id = reader.getAttributeAsInteger("id");
InternalGeometryType = static_cast<InternalType::InternalType>(reader.getAttributeAsInteger("internalGeometryType"));
InternalGeometryType = static_cast<InternalType::InternalType>(
reader.getAttributeAsInteger("internalGeometryType"));
GeometryModeFlags = GeometryModeFlagType(reader.getAttribute("geometryModeFlags"));
if(reader.hasAttribute("geometryLayer"))
if (reader.hasAttribute("geometryLayer"))
GeometryLayer = reader.getAttributeAsInteger("geometryLayer");
}
void SketchGeometryExtension::saveAttributes(Base::Writer &writer) const
void SketchGeometryExtension::saveAttributes(Base::Writer& writer) const
{
Part::GeometryPersistenceExtension::saveAttributes(writer);
writer.Stream() // << "\" id=\"" << Id // This is removed as the stored Id is not used and it may interfere with RT's future implementation
<< "\" internalGeometryType=\"" << (int) InternalGeometryType
<< "\" geometryModeFlags=\"" << GeometryModeFlags.to_string()
<< "\" geometryLayer=\"" << GeometryLayer;
// This is removed as the stored Id is not used and it may interfere with RT's future
// implementation
writer.Stream()// << "\" id=\"" << Id
<< "\" internalGeometryType=\"" << (int)InternalGeometryType << "\" geometryModeFlags=\""
<< GeometryModeFlags.to_string() << "\" geometryLayer=\"" << GeometryLayer;
}
std::unique_ptr<Part::GeometryExtension> SketchGeometryExtension::copy() const
@@ -96,53 +97,52 @@ std::unique_ptr<Part::GeometryExtension> SketchGeometryExtension::copy() const
copyAttributes(cpy.get());
#if defined (__GNUC__) && (__GNUC__ <=4)
#if defined(__GNUC__) && (__GNUC__ <= 4)
return std::move(cpy);
#else
return cpy;
#endif
}
PyObject * SketchGeometryExtension::getPyObject()
PyObject* SketchGeometryExtension::getPyObject()
{
return new SketchGeometryExtensionPy(new SketchGeometryExtension(*this));
}
bool SketchGeometryExtension::getInternalTypeFromName(std::string str, InternalType::InternalType &type)
bool SketchGeometryExtension::getInternalTypeFromName(std::string str,
InternalType::InternalType& type)
{
auto pos = std::find_if( SketchGeometryExtension::internaltype2str.begin(),
SketchGeometryExtension::internaltype2str.end(),
[str](const char * val) {
return strcmp(val,str.c_str())==0;
}
);
auto pos = std::find_if(SketchGeometryExtension::internaltype2str.begin(),
SketchGeometryExtension::internaltype2str.end(),
[str](const char* val) {
return strcmp(val, str.c_str()) == 0;
});
if( pos != SketchGeometryExtension::internaltype2str.end()) {
int index = std::distance( SketchGeometryExtension::internaltype2str.begin(), pos );
if (pos != SketchGeometryExtension::internaltype2str.end()) {
int index = std::distance(SketchGeometryExtension::internaltype2str.begin(), pos);
type = static_cast<InternalType::InternalType>(index);
return true;
type = static_cast<InternalType::InternalType>(index);
return true;
}
return false;
}
bool SketchGeometryExtension::getGeometryModeFromName(std::string str, GeometryMode::GeometryMode &type)
bool SketchGeometryExtension::getGeometryModeFromName(std::string str,
GeometryMode::GeometryMode& type)
{
auto pos = std::find_if( SketchGeometryExtension::geometrymode2str.begin(),
SketchGeometryExtension::geometrymode2str.end(),
[str](const char * val) {
return strcmp(val,str.c_str())==0;
}
);
auto pos = std::find_if(SketchGeometryExtension::geometrymode2str.begin(),
SketchGeometryExtension::geometrymode2str.end(),
[str](const char* val) {
return strcmp(val, str.c_str()) == 0;
});
if( pos != SketchGeometryExtension::geometrymode2str.end()) {
int index = std::distance( SketchGeometryExtension::geometrymode2str.begin(), pos );
if (pos != SketchGeometryExtension::geometrymode2str.end()) {
int index = std::distance(SketchGeometryExtension::geometrymode2str.begin(), pos);
type = static_cast<GeometryMode::GeometryMode>(index);
return true;
type = static_cast<GeometryMode::GeometryMode>(index);
return true;
}
return false;
}

View File

@@ -34,31 +34,35 @@
namespace Sketcher
{
namespace InternalType {
enum InternalType {
None = 0,
EllipseMajorDiameter = 1,
EllipseMinorDiameter = 2,
EllipseFocus1 = 3,
EllipseFocus2 = 4,
HyperbolaMajor = 5,
HyperbolaMinor = 6,
HyperbolaFocus = 7,
ParabolaFocus = 8,
BSplineControlPoint = 9,
BSplineKnotPoint = 10,
ParabolaFocalAxis = 11,
NumInternalGeometryType // Must be the last
};
}
namespace InternalType
{
enum InternalType
{
None = 0,
EllipseMajorDiameter = 1,
EllipseMinorDiameter = 2,
EllipseFocus1 = 3,
EllipseFocus2 = 4,
HyperbolaMajor = 5,
HyperbolaMinor = 6,
HyperbolaFocus = 7,
ParabolaFocus = 8,
BSplineControlPoint = 9,
BSplineKnotPoint = 10,
ParabolaFocalAxis = 11,
NumInternalGeometryType// Must be the last
};
}
namespace GeometryMode {
enum GeometryMode {
Blocked = 0,
Construction = 1,
NumGeometryMode // Must be the last
};
}
namespace GeometryMode
{
enum GeometryMode
{
Blocked = 0,
Construction = 1,
NumGeometryMode// Must be the last
};
}
class ISketchGeometryExtension
{
@@ -74,65 +78,103 @@ public:
// Geometry functional mode
virtual bool testGeometryMode(int flag) const = 0;
virtual void setGeometryMode(int flag, bool v=true) = 0;
virtual void setGeometryMode(int flag, bool v = true) = 0;
virtual int getGeometryLayerId() const = 0;
virtual void setGeometryLayerId(int geolayer) = 0;
};
class SketcherExport SketchGeometryExtension : public Part::GeometryPersistenceExtension, private ISketchGeometryExtension
class SketcherExport SketchGeometryExtension: public Part::GeometryPersistenceExtension,
private ISketchGeometryExtension
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
public:
SketchGeometryExtension();
explicit SketchGeometryExtension(long cid);
~SketchGeometryExtension() override = default;
std::unique_ptr<Part::GeometryExtension> copy() const override;
PyObject *getPyObject() override;
PyObject* getPyObject() override;
long getId() const override {return Id;}
void setId(long id) override {Id = id;}
long getId() const override
{
return Id;
}
void setId(long id) override
{
Id = id;
}
InternalType::InternalType getInternalType() const override {return InternalGeometryType;}
void setInternalType(InternalType::InternalType type) override {InternalGeometryType = type;}
InternalType::InternalType getInternalType() const override
{
return InternalGeometryType;
}
void setInternalType(InternalType::InternalType type) override
{
InternalGeometryType = type;
}
bool testGeometryMode(int flag) const override { return GeometryModeFlags.test((size_t)(flag)); };
void setGeometryMode(int flag, bool v=true) override { GeometryModeFlags.set((size_t)(flag), v); };
bool testGeometryMode(int flag) const override
{
return GeometryModeFlags.test((size_t)(flag));
};
void setGeometryMode(int flag, bool v = true) override
{
GeometryModeFlags.set((size_t)(flag), v);
};
int getGeometryLayerId() const override { return GeometryLayer;}
void setGeometryLayerId(int geolayer) override { GeometryLayer = geolayer;}
int getGeometryLayerId() const override
{
return GeometryLayer;
}
void setGeometryLayerId(int geolayer) override
{
GeometryLayer = geolayer;
}
constexpr static std::array<const char *,InternalType::NumInternalGeometryType> internaltype2str {{ "None", "EllipseMajorDiameter", "EllipseMinorDiameter","EllipseFocus1", "EllipseFocus2", "HyperbolaMajor", "HyperbolaMinor", "HyperbolaFocus", "ParabolaFocus", "BSplineControlPoint", "BSplineKnotPoint", "ParabolaFocalAxis" }};
constexpr static std::array<const char*, InternalType::NumInternalGeometryType>
internaltype2str {{"None",
"EllipseMajorDiameter",
"EllipseMinorDiameter",
"EllipseFocus1",
"EllipseFocus2",
"HyperbolaMajor",
"HyperbolaMinor",
"HyperbolaFocus",
"ParabolaFocus",
"BSplineControlPoint",
"BSplineKnotPoint",
"ParabolaFocalAxis"}};
constexpr static std::array<const char *,GeometryMode::NumGeometryMode> geometrymode2str {{ "Blocked", "Construction" }};
constexpr static std::array<const char*, GeometryMode::NumGeometryMode> geometrymode2str {
{"Blocked", "Construction"}};
static bool getInternalTypeFromName(std::string str, InternalType::InternalType &type);
static bool getInternalTypeFromName(std::string str, InternalType::InternalType& type);
static bool getGeometryModeFromName(std::string str, GeometryMode::GeometryMode &type);
static bool getGeometryModeFromName(std::string str, GeometryMode::GeometryMode& type);
protected:
void copyAttributes(Part::GeometryExtension * cpy) const override;
void restoreAttributes(Base::XMLReader &reader) override;
void saveAttributes(Base::Writer &writer) const override;
void copyAttributes(Part::GeometryExtension* cpy) const override;
void restoreAttributes(Base::XMLReader& reader) override;
void saveAttributes(Base::Writer& writer) const override;
private:
SketchGeometryExtension(const SketchGeometryExtension&) = default;
private:
using GeometryModeFlagType = std::bitset<32>;
long Id;
InternalType::InternalType InternalGeometryType;
GeometryModeFlagType GeometryModeFlags;
int GeometryLayer;
long Id;
InternalType::InternalType InternalGeometryType;
GeometryModeFlagType GeometryModeFlags;
int GeometryLayer;
private:
static std::atomic<long> _GeometryID;
};
} //namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_SKETCHGEOMETRYEXTENSION_H
#endif// SKETCHER_SKETCHGEOMETRYEXTENSION_H

View File

@@ -23,6 +23,7 @@
#include "PreCompiled.h"
#include "SketchGeometryExtensionPy.h"
#include "SketchGeometryExtensionPy.cpp"
@@ -34,7 +35,7 @@ std::string SketchGeometryExtensionPy::representation() const
std::stringstream str;
str << "<SketchGeometryExtension (";
if(!getSketchGeometryExtensionPtr()->getName().empty())
if (!getSketchGeometryExtensionPtr()->getName().empty())
str << "\'" << getSketchGeometryExtensionPtr()->getName() << "\', ";
str << "\"";
@@ -43,7 +44,8 @@ std::string SketchGeometryExtensionPy::representation() const
return str.str();
}
PyObject *SketchGeometryExtensionPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
// Python wrapper
PyObject* SketchGeometryExtensionPy::PyMake(struct _typeobject*, PyObject*, PyObject*)
{
// create a new instance of PointPy and the Twin object
return new SketchGeometryExtensionPy(new SketchGeometryExtension);
@@ -66,10 +68,10 @@ int SketchGeometryExtensionPy::PyInit(PyObject* args, PyObject* /*kwd*/)
}
PyErr_SetString(PyExc_TypeError, "SketchGeometryExtension constructor accepts:\n"
"-- empty parameter list\n"
"-- int\n");
PyErr_SetString(PyExc_TypeError,
"SketchGeometryExtension constructor accepts:\n"
"-- empty parameter list\n"
"-- int\n");
return -1;
}
@@ -87,12 +89,13 @@ Py::String SketchGeometryExtensionPy::getInternalType() const
{
int internaltypeindex = (int)this->getSketchGeometryExtensionPtr()->getInternalType();
if(internaltypeindex >= InternalType::NumInternalGeometryType)
if (internaltypeindex >= InternalType::NumInternalGeometryType)
throw Py::NotImplementedError("String name of enum not implemented");
std::string typestr = this->getSketchGeometryExtensionPtr()->internaltype2str[internaltypeindex];
std::string typestr =
this->getSketchGeometryExtensionPtr()->internaltype2str[internaltypeindex];
return Py::String(typestr);
return Py::String(typestr);
}
void SketchGeometryExtensionPy::setInternalType(Py::String arg)
@@ -100,7 +103,7 @@ void SketchGeometryExtensionPy::setInternalType(Py::String arg)
std::string argstr = arg;
InternalType::InternalType type;
if(SketchGeometryExtension::getInternalTypeFromName(argstr, type)) {
if (SketchGeometryExtension::getInternalTypeFromName(argstr, type)) {
this->getSketchGeometryExtensionPtr()->setInternalType(type);
return;
}
@@ -120,7 +123,8 @@ void SketchGeometryExtensionPy::setBlocked(Py::Boolean arg)
Py::Boolean SketchGeometryExtensionPy::getConstruction() const
{
return Py::Boolean(getSketchGeometryExtensionPtr()->testGeometryMode(GeometryMode::Construction));
return Py::Boolean(
getSketchGeometryExtensionPtr()->testGeometryMode(GeometryMode::Construction));
}
void SketchGeometryExtensionPy::setConstruction(Py::Boolean arg)
@@ -128,15 +132,16 @@ void SketchGeometryExtensionPy::setConstruction(Py::Boolean arg)
getSketchGeometryExtensionPtr()->setGeometryMode(GeometryMode::Construction, arg);
}
PyObject* SketchGeometryExtensionPy::testGeometryMode(PyObject *args)
PyObject* SketchGeometryExtensionPy::testGeometryMode(PyObject* args)
{
char* flag;
if (PyArg_ParseTuple(args, "s",&flag)) {
if (PyArg_ParseTuple(args, "s", &flag)) {
GeometryMode::GeometryMode mode;
if(getSketchGeometryExtensionPtr()->getGeometryModeFromName(flag, mode))
return new_reference_to(Py::Boolean(getSketchGeometryExtensionPtr()->testGeometryMode(mode)));
if (getSketchGeometryExtensionPtr()->getGeometryModeFromName(flag, mode))
return new_reference_to(
Py::Boolean(getSketchGeometryExtensionPtr()->testGeometryMode(mode)));
PyErr_SetString(PyExc_TypeError, "Flag string does not exist.");
return nullptr;
@@ -146,15 +151,15 @@ PyObject* SketchGeometryExtensionPy::testGeometryMode(PyObject *args)
return nullptr;
}
PyObject* SketchGeometryExtensionPy::setGeometryMode(PyObject *args)
PyObject* SketchGeometryExtensionPy::setGeometryMode(PyObject* args)
{
char * flag;
PyObject * bflag = Py_True;
char* flag;
PyObject* bflag = Py_True;
if (PyArg_ParseTuple(args, "s|O!", &flag, &PyBool_Type, &bflag)) {
GeometryMode::GeometryMode mode;
if(getSketchGeometryExtensionPtr()->getGeometryModeFromName(flag, mode)) {
if (getSketchGeometryExtensionPtr()->getGeometryModeFromName(flag, mode)) {
getSketchGeometryExtensionPtr()->setGeometryMode(mode, Base::asBoolean(bflag));
Py_Return;
}
@@ -177,7 +182,7 @@ void SketchGeometryExtensionPy::setGeometryLayerId(Py::Long Id)
this->getSketchGeometryExtensionPtr()->setGeometryLayerId(long(Id));
}
PyObject *SketchGeometryExtensionPy::getCustomAttributes(const char* /*attr*/) const
PyObject* SketchGeometryExtensionPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
@@ -186,4 +191,3 @@ int SketchGeometryExtensionPy::setCustomAttributes(const char* /*attr*/, PyObjec
{
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ namespace Sketcher
class SketchAnalysis;
class SketcherExport SketchObject : public Part::Part2DObject
class SketcherExport SketchObject: public Part::Part2DObject
{
PROPERTY_HEADER_WITH_OVERRIDE(Sketcher::SketchObject);
@@ -56,34 +56,38 @@ public:
The Geometry list contains the non-external Part::Geometry objects in the sketch. The list
may be accessed directly, or indirectly via getInternalGeometry().
Many of the methods in this class take geoId and posId parameters. A GeoId is a unique identifier for
geometry in the Sketch. geoId >= 0 means an index in the Geometry list. geoId < 0 refers to sketch
axes and external geometry. posId is a PointPos enum, documented in Constraint.h.
Many of the methods in this class take geoId and posId parameters. A GeoId is a unique
identifier for geometry in the Sketch. geoId >= 0 means an index in the Geometry list. geoId <
0 refers to sketch axes and external geometry. posId is a PointPos enum, documented in
Constraint.h.
*/
Part ::PropertyGeometryList Geometry;
Part ::PropertyGeometryList Geometry;
Sketcher::PropertyConstraintList Constraints;
App ::PropertyLinkSubList ExternalGeometry;
App ::PropertyBool FullyConstrained;
App ::PropertyLinkSubList ExternalGeometry;
App ::PropertyBool FullyConstrained;
/** @name methods override Feature */
//@{
short mustExecute() const override;
/// recalculate the Feature (if no recompute is needed see also solve() and solverNeedsUpdate boolean)
App::DocumentObjectExecReturn *execute() override;
/// recalculate the Feature (if no recompute is needed see also solve() and solverNeedsUpdate
/// boolean)
App::DocumentObjectExecReturn* execute() override;
/// returns the type name of the ViewProvider
const char* getViewProviderName() const override {
const char* getViewProviderName() const override
{
return "SketcherGui::ViewProviderSketch";
}
//@}
/** SketchObject can work in two modes: Recompute Mode and noRecomputes Mode
- In Recompute Mode, a recompute is necessary after each geometry addition to update the solver DoF (default)
- In NoRecomputes Mode, no recompute is necessary after a geometry addition. If a recompute is triggered
it is just less efficient.
- In Recompute Mode, a recompute is necessary after each geometry addition to update the
solver DoF (default)
- In NoRecomputes Mode, no recompute is necessary after a geometry addition. If a recompute
is triggered it is just less efficient.
This flag does not regulate whether this object will recompute or not if execute() or a recompute() is actually executed,
it just regulates whether the solver is called or not (i.e. whether it relies on
the solve of execute for the calculation)
This flag does not regulate whether this object will recompute or not if execute() or a
recompute() is actually executed, it just regulates whether the solver is called or not (i.e.
whether it relies on the solve of execute for the calculation)
*/
bool noRecomputes;
@@ -92,24 +96,22 @@ public:
\param geo - the geometry
\retval bool - true if the geometry is supported
*/
bool isSupportedGeometry(const Part::Geometry *geo) const;
bool isSupportedGeometry(const Part::Geometry* geo) const;
/*!
\brief Add geometry to a sketch - It adds a copy with a different uuid (internally uses copy() instead of clone())
\param geo - geometry to add
\param construction - true for construction lines
\retval int - GeoId of added element
\brief Add geometry to a sketch - It adds a copy with a different uuid (internally uses copy()
instead of clone()) \param geo - geometry to add \param construction - true for construction
lines \retval int - GeoId of added element
*/
int addGeometry(const Part::Geometry *geo, bool construction=false);
int addGeometry(const Part::Geometry* geo, bool construction = false);
/*!
\brief Add geometry to a sketch using up the provided newgeo. Caveat: It will use the provided newgeo with the uuid it has.
This is different from the addGeometry method with a naked pointer, where a different uuid is ensured. The caller is responsible
for provided a new or existing uuid, as necessary.
\param geo - geometry to add
\param construction - true for construction lines
\retval int - GeoId of added element
\brief Add geometry to a sketch using up the provided newgeo. Caveat: It will use the provided
newgeo with the uuid it has. This is different from the addGeometry method with a naked
pointer, where a different uuid is ensured. The caller is responsible for provided a new or
existing uuid, as necessary. \param geo - geometry to add \param construction - true for
construction lines \retval int - GeoId of added element
*/
int addGeometry(std::unique_ptr<Part::Geometry> newgeo, bool construction=false);
int addGeometry(std::unique_ptr<Part::Geometry> newgeo, bool construction = false);
/*!
\brief Add multiple geometry elements to a sketch
@@ -117,12 +119,12 @@ public:
\param construction - true for construction lines
\retval int - GeoId of last added element
*/
int addGeometry(const std::vector<Part::Geometry *> &geoList, bool construction=false);
int addGeometry(const std::vector<Part::Geometry*>& geoList, bool construction = false);
/*!
\brief Deletes indicated geometry (by geoid).
\param GeoId - the geometry to delete
\param deleteinternalgeo - if true deletes the associated and unconstraint internal geometry, otherwise deletes only the GeoId
\retval int - 0 if successful
\param deleteinternalgeo - if true deletes the associated and unconstraint internal geometry,
otherwise deletes only the GeoId \retval int - 0 if successful
*/
int delGeometry(int GeoId, bool deleteinternalgeo = true);
/// Deletes just the GeoIds indicated, it does not look for internal geometry
@@ -134,25 +136,25 @@ public:
/// deletes all the constraints of the sketch
int deleteAllConstraints();
/// add all constraints in the list
int addConstraints(const std::vector<Constraint *> &ConstraintList);
int addConstraints(const std::vector<Constraint*>& ConstraintList);
/// Copy the constraints instead of cloning them and copying the expressions if any
int addCopyOfConstraints(const SketchObject &orig);
int addCopyOfConstraints(const SketchObject& orig);
/// add constraint
int addConstraint(const Constraint *constraint);
int addConstraint(const Constraint* constraint);
/// add constraint
int addConstraint(std::unique_ptr<Constraint> constraint);
/// delete constraint
int delConstraint(int ConstrId);
/** deletes a group of constraints at once, if norecomputes is active, the default behaviour is that
* it will solve the sketch.
/** deletes a group of constraints at once, if norecomputes is active, the default behaviour is
* that it will solve the sketch.
*
* If updating the Geometry property as a consequence of a (successful) solve() is not wanted, updategeometry=false,
* prevents the update. This allows to update the solve status (e.g. dof), without updating the geometry (i.e. make it
* move to fulfil the constraints).
* If updating the Geometry property as a consequence of a (successful) solve() is not wanted,
* updategeometry=false, prevents the update. This allows to update the solve status (e.g. dof),
* without updating the geometry (i.e. make it move to fulfil the constraints).
*/
int delConstraints(std::vector<int> ConstrIds, bool updategeometry=true);
int delConstraintOnPoint(int GeoId, PointPos PosId, bool onlyCoincident=true);
int delConstraintOnPoint(int VertexId, bool onlyCoincident=true);
int delConstraints(std::vector<int> ConstrIds, bool updategeometry = true);
int delConstraintOnPoint(int GeoId, PointPos PosId, bool onlyCoincident = true);
int delConstraintOnPoint(int VertexId, bool onlyCoincident = true);
/// Deletes all constraints referencing an external geometry
int delConstraintsToExternal();
/// transfers all constraints of a point to a new point
@@ -160,9 +162,9 @@ public:
bool doNotTransformTangencies = false);
/// Carbon copy another sketch geometry and constraints
int carbonCopy(App::DocumentObject * pObj, bool construction = true);
int carbonCopy(App::DocumentObject* pObj, bool construction = true);
/// add an external geometry reference
int addExternal(App::DocumentObject *Obj, const char* SubName);
int addExternal(App::DocumentObject* Obj, const char* SubName);
/** delete external
* ExtGeoId >= 0 with 0 corresponding to the first user defined
* external geometry
@@ -178,23 +180,30 @@ public:
* id==-2 for the vertical sketch axis
* id<=-3 for user defined projected external geometries,
*/
template < typename GeometryT = Part::Geometry,
typename = typename std::enable_if<
std::is_base_of<Part::Geometry, typename std::decay<GeometryT>::type>::value
>::type
>
const GeometryT * getGeometry(int GeoId) const;
template<typename GeometryT = Part::Geometry,
typename = typename std::enable_if<std::is_base_of<
Part::Geometry, typename std::decay<GeometryT>::type>::value>::type>
const GeometryT* getGeometry(int GeoId) const;
std::unique_ptr<const GeometryFacade> getGeometryFacade(int GeoId) const;
/// returns a list of all internal geometries
const std::vector<Part::Geometry *> &getInternalGeometry() const { return Geometry.getValues(); }
const std::vector<Part::Geometry*>& getInternalGeometry() const
{
return Geometry.getValues();
}
/// returns a list of projected external geometries
const std::vector<Part::Geometry *> &getExternalGeometry() const { return ExternalGeo; }
const std::vector<Part::Geometry*>& getExternalGeometry() const
{
return ExternalGeo;
}
/// rebuilds external geometry (projection onto the sketch plane)
void rebuildExternalGeometry();
/// returns the number of external Geometry entities
int getExternalGeometryCount() const { return ExternalGeo.size(); }
int getExternalGeometryCount() const
{
return ExternalGeo.size();
}
/// retrieves a vector containing both normal and external Geometry (including the sketch axes)
std::vector<Part::Geometry*> getCompleteGeometry() const;
@@ -214,30 +223,35 @@ public:
*/
int setUpSketch();
/** Performs a full analysis of the addition of additional constraints without adding them to the sketch object */
int diagnoseAdditionalConstraints(std::vector<Sketcher::Constraint *> additionalconstraints);
/** Performs a full analysis of the addition of additional constraints without adding them to
* the sketch object */
int diagnoseAdditionalConstraints(std::vector<Sketcher::Constraint*> additionalconstraints);
/** solves the sketch and updates the geometry, but not all the dependent features (does not recompute)
When a recompute is necessary, recompute triggers execute() which solves the sketch and updates all dependent features
When a solve only is necessary (e.g. DoF changed), solve() solves the sketch and
updates the geometry (if updateGeoAfterSolving==true), but does not trigger any recompute.
@return 0 if no error, if error, the following codes in this order of priority: -4 if overconstrained,
-3 if conflicting, -1 if solver error, -2 if redundant constraints
/** solves the sketch and updates the geometry, but not all the dependent features (does not
recompute) When a recompute is necessary, recompute triggers execute() which solves the
sketch and updates all dependent features When a solve only is necessary (e.g. DoF changed),
solve() solves the sketch and updates the geometry (if updateGeoAfterSolving==true), but does
not trigger any recompute.
@return 0 if no error, if error, the following codes in this order of priority: -4 if
overconstrained, -3 if conflicting, -1 if solver error, -2 if redundant constraints
*/
int solve(bool updateGeoAfterSolving=true);
int solve(bool updateGeoAfterSolving = true);
/// set the datum of a Distance or Angle constraint and solve
int setDatum(int ConstrId, double Datum);
/// set the driving status of this constraint and solve
int setDriving(int ConstrId, bool isdriving);
/// get the driving status of this constraint
int getDriving(int ConstrId, bool &isdriving);
int getDriving(int ConstrId, bool& isdriving);
/// toggle the driving status of this constraint
int toggleDriving(int ConstrId) {return setDriving(ConstrId, !Constraints.getValues()[ConstrId]->isDriving);}
int toggleDriving(int ConstrId)
{
return setDriving(ConstrId, !Constraints.getValues()[ConstrId]->isDriving);
}
/// set the driving status of this constraint and solve
int setActive(int ConstrId, bool isactive);
/// get the driving status of this constraint
int getActive(int ConstrId, bool &isactive);
int getActive(int ConstrId, bool& isactive);
/// toggle the driving status of this constraint
int toggleActive(int ConstrId);
@@ -251,11 +265,12 @@ public:
/// set the driving status of a group of constraints at once
int setVirtualSpace(std::vector<int> constrIds, bool isinvirtualspace);
/// get the driving status of this constraint
int getVirtualSpace(int ConstrId, bool &isinvirtualspace) const;
int getVirtualSpace(int ConstrId, bool& isinvirtualspace) const;
/// toggle the driving status of this constraint
int toggleVirtualSpace(int ConstrId);
/// move this point to a new location and solve
int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative=false, bool updateGeoBeforeMoving=false);
int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative = false,
bool updateGeoBeforeMoving = false);
/// retrieves the coordinates of a point
Base::Vector3d getPoint(int GeoId, PointPos PosId) const;
@@ -271,44 +286,46 @@ public:
\param createCorner - keep geoId/pos as a Point and keep as many constraints as possible
\retval - 0 on success, -1 on failure
*/
int fillet(int geoId, PointPos pos, double radius, bool trim=true, bool preserveCorner=false);
int fillet(int geoId, PointPos pos, double radius, bool trim = true,
bool preserveCorner = false);
/*!
\brief More general form of fillet
\param geoId1, geoId2 - geoId for two lines (which don't necessarily have to coincide)
\param refPnt1, refPnt2 - reference points on the input geometry, used to influence the free fillet variables
\param radius - fillet radius
\param trim - if false, leaves the original lines untouched
\param preserveCorner - if the lines are coincident, place a Point where they meet and keep as many
of the existing constraints as possible
\retval - 0 on success, -1 on failure
\param refPnt1, refPnt2 - reference points on the input geometry, used to influence the free
fillet variables \param radius - fillet radius \param trim - if false, leaves the original
lines untouched \param preserveCorner - if the lines are coincident, place a Point where they
meet and keep as many of the existing constraints as possible \retval - 0 on success, -1 on
failure
*/
int fillet(int geoId1, int geoId2,
const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2,
double radius, bool trim=true, bool createCorner=false);
int fillet(int geoId1, int geoId2, const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2,
double radius, bool trim = true, bool createCorner = false);
/// trim a curve
int trim(int geoId, const Base::Vector3d& point);
/// extend a curve
int extend(int geoId, double increment, PointPos endPoint);
/// split a curve
int split(int geoId, const Base::Vector3d &point);
int split(int geoId, const Base::Vector3d& point);
/*!
\brief Join one or two curves at the given end points
\details The combined curve will be a b-spline
\param geoId1, posId1, geoId2, posId2: the end points to join
\retval - 0 on success, -1 on failure
*/
int join(int geoId1, Sketcher::PointPos posId1,
int geoId2, Sketcher::PointPos posId2);
int join(int geoId1, Sketcher::PointPos posId1, int geoId2, Sketcher::PointPos posId2);
/// adds symmetric geometric elements with respect to the refGeoId (line or point)
int addSymmetric(const std::vector<int> &geoIdList, int refGeoId, Sketcher::PointPos refPosId=Sketcher::PointPos::none);
/// with default parameters adds a copy of the geometric elements displaced by the displacement vector.
/// It creates an array of csize elements in the direction of the displacement vector by rsize elements in the
/// direction perpendicular to the displacement vector, wherein the modulus of this perpendicular vector is scaled by perpscale.
int addCopy(const std::vector<int> &geoIdList, const Base::Vector3d& displacement, bool moveonly = false, bool clone=false, int csize=2, int rsize=1, bool constraindisplacement = false, double perpscale = 1.0);
int addSymmetric(const std::vector<int>& geoIdList, int refGeoId,
Sketcher::PointPos refPosId = Sketcher::PointPos::none);
/// with default parameters adds a copy of the geometric elements displaced by the displacement
/// vector. It creates an array of csize elements in the direction of the displacement vector by
/// rsize elements in the direction perpendicular to the displacement vector, wherein the
/// modulus of this perpendicular vector is scaled by perpscale.
int addCopy(const std::vector<int>& geoIdList, const Base::Vector3d& displacement,
bool moveonly = false, bool clone = false, int csize = 2, int rsize = 1,
bool constraindisplacement = false, double perpscale = 1.0);
int removeAxesAlignment(const std::vector<int> &geoIdList);
int removeAxesAlignment(const std::vector<int>& geoIdList);
/// Exposes all internal geometry of an object supporting internal geometry
/*!
* \return -1 on error
@@ -317,15 +334,16 @@ public:
/*!
\brief Deletes all unused (not further constrained) internal geometry
\param GeoId - the geometry having the internal geometry to delete
\param delgeoid - if true in addition to the unused internal geometry also deletes the GeoId geometry
\retval int - returns -1 on error, otherwise the number of deleted elements
\param delgeoid - if true in addition to the unused internal geometry also deletes the GeoId
geometry \retval int - returns -1 on error, otherwise the number of deleted elements
*/
int deleteUnusedInternalGeometry(int GeoId, bool delgeoid=false);
int deleteUnusedInternalGeometry(int GeoId, bool delgeoid = false);
/*!
\brief Approximates the given geometry with a B-spline
\param GeoId - the geometry to approximate
\param delgeoid - if true in addition to the unused internal geometry also deletes the GeoId geometry
\retval bool - returns true if the approximation succeeded, or false if it did not succeed.
\param delgeoid - if true in addition to the unused internal geometry also deletes the GeoId
geometry \retval bool - returns true if the approximation succeeded, or false if it did not
succeed.
*/
bool convertToNURBS(int GeoId);
@@ -333,7 +351,8 @@ public:
\brief Increases the degree of a BSpline by degreeincrement, which defaults to 1
\param GeoId - the geometry of type bspline to increase the degree
\param degreeincrement - the increment in number of degrees to effect
\retval bool - returns true if the increase in degree succeeded, or false if it did not succeed.
\retval bool - returns true if the increase in degree succeeded, or false if it did not
succeed.
*/
bool increaseBSplineDegree(int GeoId, int degreeincrement = 1);
@@ -341,32 +360,40 @@ public:
\brief Decreases the degree of a BSpline by degreedecrement, which defaults to 1
\param GeoId - the geometry of type bspline to increase the degree
\param degreedecrement - the decrement in number of degrees to effect
\retval bool - returns true if the decrease in degree succeeded, or false if it did not succeed.
\retval bool - returns true if the decrease in degree succeeded, or false if it did not
succeed.
*/
bool decreaseBSplineDegree(int GeoId, int degreedecrement = 1);
/*!
\brief Increases or Decreases the multiplicity of a BSpline knot by the multiplicityincr param, which defaults to 1, if the result is multiplicity zero, the knot is removed
\param GeoId - the geometry of type bspline to increase the degree
\param knotIndex - the index of the knot to modify (note that index is OCC consistent, so 1<=knotindex<=knots)
\param multiplicityincr - the increment (positive value) or decrement (negative value) of multiplicity of the knot
\brief Increases or Decreases the multiplicity of a BSpline knot by the multiplicityincr param,
which defaults to 1, if the result is multiplicity zero, the knot is removed \param GeoId - the
geometry of type bspline to increase the degree \param knotIndex - the index of the knot to
modify (note that index is OCC consistent, so 1<=knotindex<=knots) \param multiplicityincr -
the increment (positive value) or decrement (negative value) of multiplicity of the knot
\retval bool - returns true if the operation succeeded, or false if it did not succeed.
*/
bool modifyBSplineKnotMultiplicity(int GeoId, int knotIndex, int multiplicityincr = 1);
/*!
\brief Inserts a knot in the BSpline at `param` with given `multiplicity`. If the knot already exists, its multiplicity is increased by `multiplicity`.
\param GeoId - the geometry of type bspline to increase the degree
\param param - the parameter value where the knot is to be placed
\param multiplicity - multiplicity of the inserted knot
\retval bool - returns true if the operation succeeded, or false if it did not succeed.
\brief Inserts a knot in the BSpline at `param` with given `multiplicity`. If the knot already
exists, its multiplicity is increased by `multiplicity`. \param GeoId - the geometry of type
bspline to increase the degree \param param - the parameter value where the knot is to be
placed \param multiplicity - multiplicity of the inserted knot \retval bool - returns true if
the operation succeeded, or false if it did not succeed.
*/
bool insertBSplineKnot(int GeoId, double param, int multiplicity = 1);
/// retrieves for a Vertex number the corresponding GeoId and PosId
void getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId) const;
int getHighestVertexIndex() const { return VertexId2GeoId.size() - 1; } // Most recently created
int getHighestCurveIndex() const { return Geometry.getSize() - 1; }
void getGeoVertexIndex(int VertexId, int& GeoId, PointPos& PosId) const;
int getHighestVertexIndex() const
{
return VertexId2GeoId.size() - 1;
}// Most recently created
int getHighestCurveIndex() const
{
return Geometry.getSize() - 1;
}
void rebuildVertexIndex();
/// retrieves for a GeoId and PosId the Vertex number
@@ -374,28 +401,32 @@ public:
// retrieves an array of maps, each map containing the points that are coincidence by virtue of
// any number of direct or indirect coincidence constraints
const std::vector< std::map<int, Sketcher::PointPos> > getCoincidenceGroups();
// returns if the given geoId is fixed (coincident) with external geometry on any of the possible relevant points
void isCoincidentWithExternalGeometry(int GeoId, bool &start_external, bool &mid_external, bool &end_external);
// returns a map containing all the GeoIds that are coincident with the given point as keys, and the PosIds as values associated
// with the keys.
const std::vector<std::map<int, Sketcher::PointPos>> getCoincidenceGroups();
// returns if the given geoId is fixed (coincident) with external geometry on any of the
// possible relevant points
void isCoincidentWithExternalGeometry(int GeoId, bool& start_external, bool& mid_external,
bool& end_external);
// returns a map containing all the GeoIds that are coincident with the given point as keys, and
// the PosIds as values associated with the keys.
const std::map<int, Sketcher::PointPos> getAllCoincidentPoints(int GeoId, PointPos PosId);
/// retrieves for a Vertex number a list with all coincident points (sharing a single coincidence constraint)
void getDirectlyCoincidentPoints(int GeoId, PointPos PosId, std::vector<int> &GeoIdList,
std::vector<PointPos> &PosIdList);
void getDirectlyCoincidentPoints(int VertexId, std::vector<int> &GeoIdList, std::vector<PointPos> &PosIdList);
/// retrieves for a Vertex number a list with all coincident points (sharing a single
/// coincidence constraint)
void getDirectlyCoincidentPoints(int GeoId, PointPos PosId, std::vector<int>& GeoIdList,
std::vector<PointPos>& PosIdList);
void getDirectlyCoincidentPoints(int VertexId, std::vector<int>& GeoIdList,
std::vector<PointPos>& PosIdList);
bool arePointsCoincident(int GeoId1, PointPos PosId1, int GeoId2, PointPos PosId2);
/// returns a list of indices of all constraints involving given GeoId
void getConstraintIndices(int GeoId, std::vector<int> &constraintList);
void getConstraintIndices(int GeoId, std::vector<int>& constraintList);
/// generates a warning message about constraint conflicts and appends it to the given message
static void appendConflictMsg(const std::vector<int> &conflicting, std::string &msg);
static void appendConflictMsg(const std::vector<int>& conflicting, std::string& msg);
/// generates a warning message about redundant constraints and appends it to the given message
static void appendRedundantMsg(const std::vector<int> &redundant, std::string &msg);
static void appendRedundantMsg(const std::vector<int>& redundant, std::string& msg);
/// generates a warning message about malformed constraints and appends it to the given message
static void appendMalformedConstraintsMsg(const std::vector<int> &malformed, std::string &msg);
static void appendMalformedConstraintsMsg(const std::vector<int>& malformed, std::string& msg);
double calculateAngleViaPoint(int geoId1, int geoId2, double px, double py);
bool isPointOnCurve(int geoIdCurve, double px, double py);
@@ -404,23 +435,24 @@ public:
/// returns whether a given constraint has an associated expression or not
bool constraintHasExpression(int constrid) const;
///porting functions
/// porting functions
int port_reversedExternalArcs(bool justAnalyze);
// from base class
PyObject *getPyObject() override;
PyObject* getPyObject() override;
unsigned int getMemSize() const override;
void Save(Base::Writer &/*writer*/) const override;
void Restore(Base::XMLReader &/*reader*/) override;
void Save(Base::Writer& /*writer*/) const override;
void Restore(Base::XMLReader& /*reader*/) override;
/// returns the number of construction lines (to be used as axes)
int getAxisCount() const override;
/// retrieves an axis iterating through the construction lines of the sketch (indices start at 0)
/// retrieves an axis iterating through the construction lines of the sketch (indices start at
/// 0)
Base::Axis getAxis(int axId) const override;
/// verify and accept the assigned geometry
void acceptGeometry() override;
/// Check if constraint has invalid indexes
bool evaluateConstraint(const Constraint *constraint) const;
bool evaluateConstraint(const Constraint* constraint) const;
/// Check for constraints with invalid indexes
bool evaluateConstraints() const;
/// Remove constraints with invalid indexes
@@ -431,109 +463,170 @@ public:
void validateExternalLinks();
/// gets DoF of last solver execution
inline int getLastDoF() const {return lastDoF;}
inline int getLastDoF() const
{
return lastDoF;
}
/// gets HasConflicts status of last solver execution
inline bool getLastHasConflicts() const {return lastHasConflict;}
inline bool getLastHasConflicts() const
{
return lastHasConflict;
}
/// gets HasRedundancies status of last solver execution
inline bool getLastHasRedundancies() const {return lastHasRedundancies;}
inline bool getLastHasRedundancies() const
{
return lastHasRedundancies;
}
/// gets HasRedundancies status of last solver execution
inline bool getLastHasPartialRedundancies() const {return lastHasPartialRedundancies;}
inline bool getLastHasPartialRedundancies() const
{
return lastHasPartialRedundancies;
}
/// gets HasMalformedConstraints status of last solver execution
inline bool getLastHasMalformedConstraints() const {return lastHasMalformedConstraints;}
inline bool getLastHasMalformedConstraints() const
{
return lastHasMalformedConstraints;
}
/// gets solver status of last solver execution
inline int getLastSolverStatus() const {return lastSolverStatus;}
inline int getLastSolverStatus() const
{
return lastSolverStatus;
}
/// gets solver SolveTime of last solver execution
inline float getLastSolveTime() const {return lastSolveTime;}
inline float getLastSolveTime() const
{
return lastSolveTime;
}
/// gets the conflicting constraints of the last solver execution
inline const std::vector<int> &getLastConflicting() const { return lastConflicting; }
inline const std::vector<int>& getLastConflicting() const
{
return lastConflicting;
}
/// gets the redundant constraints of last solver execution
inline const std::vector<int> &getLastRedundant() const { return lastRedundant; }
inline const std::vector<int>& getLastRedundant() const
{
return lastRedundant;
}
/// gets the redundant constraints of last solver execution
inline const std::vector<int> &getLastPartiallyRedundant() const { return lastPartiallyRedundant; }
inline const std::vector<int>& getLastPartiallyRedundant() const
{
return lastPartiallyRedundant;
}
/// gets the redundant constraints of last solver execution
inline const std::vector<int> &getLastMalformedConstraints() const { return lastMalformedConstraints; }
inline const std::vector<int>& getLastMalformedConstraints() const
{
return lastMalformedConstraints;
}
public: /* Solver exposed interface */
/// gets the solved sketch as a reference
inline const Sketch &getSolvedSketch() const {return solvedSketch;}
/// enables/disables solver initial solution recalculation when moving point mode (useful for dragging)
inline void setRecalculateInitialSolutionWhileMovingPoint(bool recalculateInitialSolutionWhileMovingPoint)
{solvedSketch.setRecalculateInitialSolutionWhileMovingPoint(recalculateInitialSolutionWhileMovingPoint);}
/// Forwards a request for a temporary initMove to the solver using the current sketch state as a reference (enables dragging)
inline int initTemporaryMove(int geoId, PointPos pos, bool fine=true);
/// Forwards a request for a temporary initBSplinePieceMove to the solver using the current sketch state as a reference (enables dragging)
inline int initTemporaryBSplinePieceMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint, bool fine=true);
/** Forwards a request for point or curve temporary movement to the solver using the current state as a reference (enables dragging).
* NOTE: A temporary move operation must always be preceded by a initTemporaryMove() operation.
inline const Sketch& getSolvedSketch() const
{
return solvedSketch;
}
/// enables/disables solver initial solution recalculation when moving point mode (useful for
/// dragging)
inline void
setRecalculateInitialSolutionWhileMovingPoint(bool recalculateInitialSolutionWhileMovingPoint)
{
solvedSketch.setRecalculateInitialSolutionWhileMovingPoint(
recalculateInitialSolutionWhileMovingPoint);
}
/// Forwards a request for a temporary initMove to the solver using the current sketch state as
/// a reference (enables dragging)
inline int initTemporaryMove(int geoId, PointPos pos, bool fine = true);
/// Forwards a request for a temporary initBSplinePieceMove to the solver using the current
/// sketch state as a reference (enables dragging)
inline int initTemporaryBSplinePieceMove(int geoId, PointPos pos,
const Base::Vector3d& firstPoint, bool fine = true);
/** Forwards a request for point or curve temporary movement to the solver using the current
* state as a reference (enables dragging). NOTE: A temporary move operation must always be
* preceded by a initTemporaryMove() operation.
*/
inline int moveTemporaryPoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative=false);
inline int moveTemporaryPoint(int geoId, PointPos pos, Base::Vector3d toPoint,
bool relative = false);
/// forwards a request to update an extension of a geometry of the solver to the solver.
inline void updateSolverExtension(int geoId, std::unique_ptr<Part::GeometryExtension> && ext)
{ return solvedSketch.updateExtension(geoId, std::move(ext));}
inline void updateSolverExtension(int geoId, std::unique_ptr<Part::GeometryExtension>&& ext)
{
return solvedSketch.updateExtension(geoId, std::move(ext));
}
public:
/// returns the geometric elements/vertex which the solver detects as having dependent parameters.
/// these parameters relate to not fully constraint edges/vertices.
void getGeometryWithDependentParameters(std::vector<std::pair<int,PointPos>>& geometrymap);
/// returns the geometric elements/vertex which the solver detects as having dependent
/// parameters. these parameters relate to not fully constraint edges/vertices.
void getGeometryWithDependentParameters(std::vector<std::pair<int, PointPos>>& geometrymap);
/// Flag to allow external geometry from other bodies than the one this sketch belongs to
bool isAllowedOtherBody() const {
bool isAllowedOtherBody() const
{
return allowOtherBody;
}
void setAllowOtherBody(bool on) {
void setAllowOtherBody(bool on)
{
allowOtherBody = on;
}
/// Flag to allow carbon copy from misaligned geometry
bool isAllowedUnaligned() const {
bool isAllowedUnaligned() const
{
return allowUnaligned;
}
void setAllowUnaligned(bool on) {
void setAllowUnaligned(bool on)
{
allowUnaligned = on;
}
enum eReasonList{
enum eReasonList
{
rlAllowed,
rlOtherDoc,
rlCircularReference,
rlOtherPart,
rlOtherBody,
rlOtherBodyWithLinks, // for carbon copy
rlNotASketch, // for carbon copy
rlNonParallel, // for carbon copy
rlAxesMisaligned, // for carbon copy
rlOriginsMisaligned // for carbon copy
rlOtherBodyWithLinks,// for carbon copy
rlNotASketch, // for carbon copy
rlNonParallel, // for carbon copy
rlAxesMisaligned, // for carbon copy
rlOriginsMisaligned // for carbon copy
};
/// Return true if this object is allowed as external geometry for the
/// sketch. rsn argument receives the reason for disallowing.
bool isExternalAllowed(App::Document *pDoc, App::DocumentObject *pObj, eReasonList* rsn = nullptr) const;
bool isExternalAllowed(App::Document* pDoc, App::DocumentObject* pObj,
eReasonList* rsn = nullptr) const;
bool isCarbonCopyAllowed(App::Document *pDoc, App::DocumentObject *pObj, bool & xinv, bool & yinv, eReasonList* rsn = nullptr) const;
bool isCarbonCopyAllowed(App::Document* pDoc, App::DocumentObject* pObj, bool& xinv, bool& yinv,
eReasonList* rsn = nullptr) const;
bool isPerformingInternalTransaction() const {return internaltransaction;};
bool isPerformingInternalTransaction() const
{
return internaltransaction;
};
/** retrieves intersection points of this curve with the closest two curves around a point of this curve.
/** retrieves intersection points of this curve with the closest two curves around a point of
* this curve.
* - it includes internal and external intersecting geometry.
* - it returns GeoEnum::GeoUndef if no intersection is found.
*/
bool seekTrimPoints(int GeoId, const Base::Vector3d &point,
int &GeoId1, Base::Vector3d &intersect1,
int &GeoId2, Base::Vector3d &intersect2);
bool seekTrimPoints(int GeoId, const Base::Vector3d& point, int& GeoId1,
Base::Vector3d& intersect1, int& GeoId2, Base::Vector3d& intersect2);
public:
// Analyser functions
int autoConstraint(double precision = Precision::Confusion() * 1000, double angleprecision = M_PI/20, bool includeconstruction = true);
int autoConstraint(double precision = Precision::Confusion() * 1000,
double angleprecision = M_PI / 20, bool includeconstruction = true);
int detectMissingPointOnPointConstraints(double precision = Precision::Confusion() * 1000, bool includeconstruction = true);
void analyseMissingPointOnPointCoincident(double angleprecision = M_PI/8);
int detectMissingVerticalHorizontalConstraints(double angleprecision = M_PI/8);
int detectMissingPointOnPointConstraints(double precision = Precision::Confusion() * 1000,
bool includeconstruction = true);
void analyseMissingPointOnPointCoincident(double angleprecision = M_PI / 8);
int detectMissingVerticalHorizontalConstraints(double angleprecision = M_PI / 8);
int detectMissingEqualityConstraints(double precision);
std::vector<ConstraintIds> &getMissingPointOnPointConstraints();
std::vector<ConstraintIds> &getMissingVerticalHorizontalConstraints();
std::vector<ConstraintIds> &getMissingLineEqualityConstraints();
std::vector<ConstraintIds> &getMissingRadiusConstraints();
std::vector<ConstraintIds>& getMissingPointOnPointConstraints();
std::vector<ConstraintIds>& getMissingVerticalHorizontalConstraints();
std::vector<ConstraintIds>& getMissingLineEqualityConstraints();
std::vector<ConstraintIds>& getMissingRadiusConstraints();
void setMissingRadiusConstraints(std::vector<ConstraintIds> &cl);
void setMissingRadiusConstraints(std::vector<ConstraintIds>& cl);
void setMissingLineEqualityConstraints(std::vector<ConstraintIds>& cl);
void setMissingVerticalHorizontalConstraints(std::vector<ConstraintIds>& cl);
void setMissingPointOnPointConstraints(std::vector<ConstraintIds>& cl);
@@ -551,9 +644,9 @@ public:
// Validation routines
std::vector<Base::Vector3d> getOpenVertices() const;
public: // geometry extension functionalities for single element sketch object user convenience
public:// geometry extension functionalities for single element sketch object user convenience
int setGeometryId(int GeoId, long id);
int getGeometryId(int GeoId, long &id) const;
int getGeometryId(int GeoId, long& id) const;
protected:
/// get called by the container when a property has changed
@@ -561,28 +654,31 @@ protected:
void onDocumentRestored() override;
void restoreFinished() override;
void setExpression(const App::ObjectIdentifier &path, std::shared_ptr<App::Expression> expr) override;
void setExpression(const App::ObjectIdentifier& path,
std::shared_ptr<App::Expression> expr) override;
std::string validateExpression(const App::ObjectIdentifier &path, std::shared_ptr<const App::Expression> expr);
std::string validateExpression(const App::ObjectIdentifier& path,
std::shared_ptr<const App::Expression> expr);
void constraintsRenamed(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> &renamed);
void constraintsRemoved(const std::set<App::ObjectIdentifier> &removed);
void constraintsRenamed(const std::map<App::ObjectIdentifier, App::ObjectIdentifier>& renamed);
void constraintsRemoved(const std::set<App::ObjectIdentifier>& removed);
/*!
\brief Returns a list of supported geometries from the input list
\param geoList - the geometry list
\retval list - the supported geometry list
*/
std::vector<Part::Geometry *> supportedGeometry(const std::vector<Part::Geometry *> &geoList) const;
std::vector<Part::Geometry*>
supportedGeometry(const std::vector<Part::Geometry*>& geoList) const;
/*!
\brief Transfer constraints on lines being filleted.
Since filleting moves the endpoints of the input geometry, existing constraints may no longer be
sensible. If fillet() was called with preserveCorner=false, the constraints are simply deleted.
But if the lines are coincident and preserveCorner=true, we can preserve most constraints on the
old end points by moving them to the preserved corner, or transforming distance constraints on
straight lines into point-to-point distance constraints.
Since filleting moves the endpoints of the input geometry, existing constraints may no longer
be sensible. If fillet() was called with preserveCorner=false, the constraints are simply
deleted. But if the lines are coincident and preserveCorner=true, we can preserve most
constraints on the old end points by moving them to the preserved corner, or transforming
distance constraints on straight lines into point-to-point distance constraints.
\param geoId1, podId1, geoId2, posId2 - The two lines that have just been filleted
*/
@@ -597,43 +693,39 @@ protected:
// migration functions
void migrateSketch();
static void appendConstraintsMsg(const std::vector<int> &vector,
const std::string & singularmsg,
const std::string & pluralmsg,
std::string &msg);
static void appendConstraintsMsg(const std::vector<int>& vector, const std::string& singularmsg,
const std::string& pluralmsg, std::string& msg);
// retrieves redundant, conflicting and malformed constraint information from the solver
void retrieveSolverDiagnostics();
// retrieves whether a geometry blocked state corresponds to this constraint
// returns true of the constraint is of Block type, false otherwise
bool getBlockedState(const Constraint * cstr, bool & blockedstate) const;
bool getBlockedState(const Constraint* cstr, bool& blockedstate) const;
// retrieves the geometry blocked state corresponding to this constraint
// returns true of the constraint is of InternalAlignment type, false otherwise
bool getInternalTypeState(const Constraint * cstr, Sketcher::InternalType::InternalType & internaltypestate) const;
bool getInternalTypeState(const Constraint* cstr,
Sketcher::InternalType::InternalType& internaltypestate) const;
// Checks whether the geometry state stored in the geometry extension matches the current sketcher situation (e.g. constraints)
// and corrects the state if not matching.
// Checks whether the geometry state stored in the geometry extension matches the current
// sketcher situation (e.g. constraints) and corrects the state if not matching.
void synchroniseGeometryState();
// helper function to create a new constraint and move it to the Constraint Property
void addConstraint( Sketcher::ConstraintType constrType,
int firstGeoId,
Sketcher::PointPos firstPos,
int secondGeoId = GeoEnum::GeoUndef,
Sketcher::PointPos secondPos = Sketcher::PointPos::none,
int thirdGeoId = GeoEnum::GeoUndef,
Sketcher::PointPos thirdPos = Sketcher::PointPos::none);
void addConstraint(Sketcher::ConstraintType constrType, int firstGeoId,
Sketcher::PointPos firstPos, int secondGeoId = GeoEnum::GeoUndef,
Sketcher::PointPos secondPos = Sketcher::PointPos::none,
int thirdGeoId = GeoEnum::GeoUndef,
Sketcher::PointPos thirdPos = Sketcher::PointPos::none);
// creates a new constraint
std::unique_ptr<Constraint> createConstraint( Sketcher::ConstraintType constrType,
int firstGeoId,
Sketcher::PointPos firstPos,
int secondGeoId = GeoEnum::GeoUndef,
Sketcher::PointPos secondPos = Sketcher::PointPos::none,
int thirdGeoId = GeoEnum::GeoUndef,
Sketcher::PointPos thirdPos = Sketcher::PointPos::none);
std::unique_ptr<Constraint>
createConstraint(Sketcher::ConstraintType constrType, int firstGeoId,
Sketcher::PointPos firstPos, int secondGeoId = GeoEnum::GeoUndef,
Sketcher::PointPos secondPos = Sketcher::PointPos::none,
int thirdGeoId = GeoEnum::GeoUndef,
Sketcher::PointPos thirdPos = Sketcher::PointPos::none);
private:
/// Flag to allow external geometry from other bodies than the one this sketch belongs to
@@ -642,15 +734,16 @@ private:
/// Flag to allow carbon copy from misaligned geometry
bool allowUnaligned;
std::vector<Part::Geometry *> ExternalGeo;
std::vector<Part::Geometry*> ExternalGeo;
std::vector<int> VertexId2GeoId;
std::vector<PointPos> VertexId2PosId;
Sketch solvedSketch;
/** this internal flag indicate that an operation modifying the geometry, but not the DoF of the sketch took place (e.g. toggle construction),
so if next action is a movement of a point (movePoint), the geometry must be updated first.
/** this internal flag indicate that an operation modifying the geometry, but not the DoF of the
sketch took place (e.g. toggle construction), so if next action is a movement of a point
(movePoint), the geometry must be updated first.
*/
bool solverNeedsUpdate;
@@ -672,73 +765,79 @@ private:
bool AutoLockTangencyAndPerpty(Constraint* cstr, bool bForce = false, bool bLock = true);
// Geometry Extensions is used to store on geometry a state that is enforced by pre-existing constraints
// Like Block constraint and InternalAlignment constraint. This enables (more) convenient handling in ViewProviderSketch
// and solver.
// Geometry Extensions is used to store on geometry a state that is enforced by pre-existing
// constraints Like Block constraint and InternalAlignment constraint. This enables (more)
// convenient handling in ViewProviderSketch and solver.
//
// These functions are responsible for updating the Geometry State, currently Geometry Mode (Blocked) and
// Geometry InternalType (BSplineKnot, BSplinePole).
// These functions are responsible for updating the Geometry State, currently Geometry Mode
// (Blocked) and Geometry InternalType (BSplineKnot, BSplinePole).
//
// The data life model for handling this state is as follows:
// 1. Upon restore, any migration is handled to set the status for legacy files (backwards compatibility)
// 2. Functionality adding constraints (of the relevant type) calls addGeometryState to set the status
// 3. Functionality removing constraints (of the relevant type) calls removeGeometryState to remove the status
// 1. Upon restore, any migration is handled to set the status for legacy files (backwards
// compatibility)
// 2. Functionality adding constraints (of the relevant type) calls addGeometryState to set the
// status
// 3. Functionality removing constraints (of the relevant type) calls removeGeometryState to
// remove the status
// 4. Save mechanism will ensure persistence.
void addGeometryState(const Constraint* cstr) const;
void removeGeometryState(const Constraint* cstr) const;
SketchAnalysis * analyser;
SketchAnalysis* analyser;
bool internaltransaction;
bool managedoperation; // indicates whether changes to properties are the deed of SketchObject or not (for input validation)
// indicates whether changes to properties are the deed of SketchObject or not (for input
// validation)
bool managedoperation;
};
inline int SketchObject::initTemporaryMove(int geoId, PointPos pos, bool fine/*=true*/)
inline int SketchObject::initTemporaryMove(int geoId, PointPos pos, bool fine /*=true*/)
{
// if a previous operation did not update the geometry (including geometry extensions)
// or constraints (including any deleted pointer, as in renameConstraint) of the solver,
// here we update them before starting a temporary operation.
if(solverNeedsUpdate)
if (solverNeedsUpdate)
solve();
return solvedSketch.initMove(geoId,pos,fine);
return solvedSketch.initMove(geoId, pos, fine);
}
inline int SketchObject::initTemporaryBSplinePieceMove(int geoId, PointPos pos, const Base::Vector3d& firstPoint, bool fine)
inline int SketchObject::initTemporaryBSplinePieceMove(int geoId, PointPos pos,
const Base::Vector3d& firstPoint, bool fine)
{
// if a previous operation did not update the geometry (including geometry extensions)
// or constraints (including any deleted pointer, as in renameConstraint) of the solver,
// here we update them before starting a temporary operation.
if(solverNeedsUpdate)
if (solverNeedsUpdate)
solve();
return solvedSketch.initBSplinePieceMove(geoId,pos,firstPoint,fine);
return solvedSketch.initBSplinePieceMove(geoId, pos, firstPoint, fine);
}
inline int SketchObject::moveTemporaryPoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative/*=false*/)
inline int SketchObject::moveTemporaryPoint(int geoId, PointPos pos, Base::Vector3d toPoint,
bool relative /*=false*/)
{
return solvedSketch.movePoint(geoId, pos, toPoint, relative);
}
template < typename GeometryT,
typename >
const GeometryT * SketchObject::getGeometry(int GeoId) const
template<typename GeometryT, typename>
const GeometryT* SketchObject::getGeometry(int GeoId) const
{
if (GeoId >= 0) {
const std::vector<Part::Geometry *> &geomlist = getInternalGeometry();
const std::vector<Part::Geometry*>& geomlist = getInternalGeometry();
if (GeoId < int(geomlist.size()))
return static_cast<GeometryT *>(geomlist[GeoId]);
return static_cast<GeometryT*>(geomlist[GeoId]);
}
else if (-GeoId <= int(ExternalGeo.size()))
return static_cast<GeometryT *>(ExternalGeo[-GeoId-1]);
return static_cast<GeometryT*>(ExternalGeo[-GeoId - 1]);
return nullptr;
}
using SketchObjectPython = App::FeaturePythonT<SketchObject>;
} //namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_SKETCHOBJECT_H
#endif// SKETCHER_SKETCHOBJECT_H

File diff suppressed because it is too large Load Diff

View File

@@ -33,8 +33,11 @@ PROPERTY_SOURCE(Sketcher::SketchObjectSF, Part::Part2DObject)
SketchObjectSF::SketchObjectSF()
{
ADD_PROPERTY_TYPE(SketchFlatFile,(nullptr),"",(App::PropertyType)(App::Prop_None),
"SketchFlat file (*.skf) which defines this sketch");
ADD_PROPERTY_TYPE(SketchFlatFile,
(nullptr),
"",
(App::PropertyType)(App::Prop_None),
"SketchFlat file (*.skf) which defines this sketch");
}
short SketchObjectSF::mustExecute() const
@@ -44,9 +47,11 @@ short SketchObjectSF::mustExecute() const
return 0;
}
App::DocumentObjectExecReturn *SketchObjectSF::execute()
App::DocumentObjectExecReturn* SketchObjectSF::execute()
{
Base::Console().Warning("%s: This feature is deprecated and won't be longer supported in future FreeCAD versions\n",this->getNameInDocument());
// do nothing
Base::Console().Warning(
"%s: This feature is deprecated and won't be longer supported in future FreeCAD versions\n",
this->getNameInDocument());
// do nothing
return App::DocumentObject::StdReturn;
}

View File

@@ -31,7 +31,7 @@
namespace Sketcher
{
class SketchObjectSF :public Part::Part2DObject
class SketchObjectSF: public Part::Part2DObject
{
PROPERTY_HEADER_WITH_OVERRIDE(Sketcher::SketchObjectSF);
@@ -44,21 +44,19 @@ public:
/** @name methods override Feature */
//@{
/// recalculate the Feature
App::DocumentObjectExecReturn *execute() override;
App::DocumentObjectExecReturn* execute() override;
short mustExecute() const override;
/// Uses the standard ViewProvider
//const char* getViewProviderName(void) const {
// return "SketcherGui::ViewProviderSketchSF";
//}
// const char* getViewProviderName(void) const {
// return "SketcherGui::ViewProviderSketchSF";
// }
//@}
bool save(const char* FileName);
bool load(const char* FileName);
};
} //namespace Part
}// namespace Sketcher
#endif // SKETCH_SKETCHOBJECTSF_H
#endif// SKETCH_SKETCHOBJECTSF_H

View File

@@ -24,8 +24,8 @@
// inclusion of the generated files (generated out of SketchObjectSFPy.xml)
#include "SketchObjectSFPy.h"
#include "SketchObjectSFPy.cpp"
#include "SketchObjectSFPy.cpp"
using namespace Sketcher;
@@ -35,12 +35,12 @@ std::string SketchObjectSFPy::representation() const
return "<SketchObjectSF object>";
}
PyObject *SketchObjectSFPy::getCustomAttributes(const char* /*attr*/) const
PyObject* SketchObjectSFPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
int SketchObjectSFPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
return 0;
}

View File

@@ -28,9 +28,10 @@
// inclusion of the generated files (generated out of SketchPy.xml)
#include "SketchPy.h"
#include "SketchPy.cpp"
#include "ConstraintPy.h"
#include "SketchPy.cpp"
#include "ConstraintPy.h"
using namespace Sketcher;
using namespace Part;
@@ -41,7 +42,7 @@ std::string SketchPy::representation() const
return std::string("<Sketch object>");
}
PyObject *SketchPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
PyObject* SketchPy::PyMake(struct _typeobject*, PyObject*, PyObject*)// Python wrapper
{
// create a new instance of SketchPy and the Twin object
return new SketchPy(new Sketch());
@@ -55,7 +56,7 @@ int SketchPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
// +++ methods implementer ++++++++++++++++++++++++++++++++++++++++++++++++
PyObject* SketchPy::solve(PyObject *args)
PyObject* SketchPy::solve(PyObject* args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
@@ -63,23 +64,23 @@ PyObject* SketchPy::solve(PyObject *args)
return Py::new_reference_to(Py::Long(getSketchPtr()->solve()));
}
PyObject* SketchPy::addGeometry(PyObject *args)
PyObject* SketchPy::addGeometry(PyObject* args)
{
PyObject *pcObj;
PyObject* pcObj;
if (!PyArg_ParseTuple(args, "O", &pcObj))
return nullptr;
if (PyObject_TypeCheck(pcObj, &(Part::GeometryPy::Type))) {
Part::Geometry *geo = static_cast<Part::GeometryPy*>(pcObj)->getGeometryPtr();
Part::Geometry* geo = static_cast<Part::GeometryPy*>(pcObj)->getGeometryPtr();
return Py::new_reference_to(Py::Long(this->getSketchPtr()->addGeometry(geo)));
}
else if (PyObject_TypeCheck(pcObj, &(PyList_Type)) ||
PyObject_TypeCheck(pcObj, &(PyTuple_Type))) {
std::vector<Part::Geometry *> geoList;
else if (PyObject_TypeCheck(pcObj, &(PyList_Type))
|| PyObject_TypeCheck(pcObj, &(PyTuple_Type))) {
std::vector<Part::Geometry*> geoList;
Py::Sequence list(pcObj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(Part::GeometryPy::Type))) {
Part::Geometry *geo = static_cast<Part::GeometryPy*>((*it).ptr())->getGeometryPtr();
Part::Geometry* geo = static_cast<Part::GeometryPy*>((*it).ptr())->getGeometryPtr();
geoList.push_back(geo);
}
}
@@ -87,7 +88,7 @@ PyObject* SketchPy::addGeometry(PyObject *args)
int ret = this->getSketchPtr()->addGeometry(geoList) + 1;
std::size_t numGeo = geoList.size();
Py::Tuple tuple(numGeo);
for (std::size_t i=0; i<numGeo; ++i) {
for (std::size_t i = 0; i < numGeo; ++i) {
int geoId = ret - int(numGeo - i);
tuple.setItem(i, Py::Long(geoId));
}
@@ -99,9 +100,9 @@ PyObject* SketchPy::addGeometry(PyObject *args)
throw Py::TypeError(error);
}
PyObject* SketchPy::addConstraint(PyObject *args)
PyObject* SketchPy::addConstraint(PyObject* args)
{
PyObject *pcObj;
PyObject* pcObj;
if (!PyArg_ParseTuple(args, "O", &pcObj))
return nullptr;
@@ -110,7 +111,7 @@ PyObject* SketchPy::addConstraint(PyObject *args)
Py::Sequence list(pcObj);
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
if (PyObject_TypeCheck((*it).ptr(), &(ConstraintPy::Type))) {
Constraint *con = static_cast<ConstraintPy*>((*it).ptr())->getConstraintPtr();
Constraint* con = static_cast<ConstraintPy*>((*it).ptr())->getConstraintPtr();
values.push_back(con);
}
}
@@ -118,14 +119,14 @@ PyObject* SketchPy::addConstraint(PyObject *args)
int ret = getSketchPtr()->addConstraints(values) + 1;
std::size_t numCon = values.size();
Py::Tuple tuple(numCon);
for (std::size_t i=0; i<numCon; ++i) {
for (std::size_t i = 0; i < numCon; ++i) {
int conId = ret - int(numCon - i);
tuple.setItem(i, Py::Long(conId));
}
return Py::new_reference_to(tuple);
}
else if(PyObject_TypeCheck(pcObj, &(ConstraintPy::Type))) {
ConstraintPy *pcObject = static_cast<ConstraintPy*>(pcObj);
else if (PyObject_TypeCheck(pcObj, &(ConstraintPy::Type))) {
ConstraintPy* pcObject = static_cast<ConstraintPy*>(pcObj);
int ret = getSketchPtr()->addConstraint(pcObject->getConstraintPtr());
return Py::new_reference_to(Py::Long(ret));
}
@@ -136,7 +137,7 @@ PyObject* SketchPy::addConstraint(PyObject *args)
}
}
PyObject* SketchPy::clear(PyObject *args)
PyObject* SketchPy::clear(PyObject* args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
@@ -146,23 +147,25 @@ PyObject* SketchPy::clear(PyObject *args)
Py_RETURN_NONE;
}
PyObject* SketchPy::movePoint(PyObject *args)
PyObject* SketchPy::movePoint(PyObject* args)
{
int index1,index2;
PyObject *pcObj;
int relative=0;
if (!PyArg_ParseTuple(args, "iiO!|i", &index1,&index2,&(Base::VectorPy::Type),&pcObj,&relative))
int index1, index2;
PyObject* pcObj;
int relative = 0;
if (!PyArg_ParseTuple(
args, "iiO!|i", &index1, &index2, &(Base::VectorPy::Type), &pcObj, &relative))
return nullptr;
Base::Vector3d* toPoint = static_cast<Base::VectorPy*>(pcObj)->getVectorPtr();
return Py::new_reference_to(Py::Long(getSketchPtr()->movePoint(index1,static_cast<Sketcher::PointPos>(index2),*toPoint,(relative>0))));
return Py::new_reference_to(Py::Long(getSketchPtr()->movePoint(
index1, static_cast<Sketcher::PointPos>(index2), *toPoint, (relative > 0))));
}
// +++ attributes implementer ++++++++++++++++++++++++++++++++++++++++++++++++
Py::Long SketchPy::getConstraint() const
{
//return Py::Int();
// return Py::Int();
throw Py::AttributeError("Not yet implemented");
}
@@ -170,7 +173,7 @@ Py::Tuple SketchPy::getConflicts() const
{
std::vector<int> c = getSketchPtr()->getConflicting();
Py::Tuple t(c.size());
for (std::size_t i=0; i<c.size(); i++) {
for (std::size_t i = 0; i < c.size(); i++) {
t.setItem(i, Py::Long(c[i]));
}
@@ -181,7 +184,7 @@ Py::Tuple SketchPy::getRedundancies() const
{
std::vector<int> c = getSketchPtr()->getRedundant();
Py::Tuple t(c.size());
for (std::size_t i=0; i<c.size(); i++) {
for (std::size_t i = 0; i < c.size(); i++) {
t.setItem(i, Py::Long(c[i]));
}
@@ -202,7 +205,7 @@ Py::Object SketchPy::getShape() const
// +++ custom attributes implementer ++++++++++++++++++++++++++++++++++++++++
PyObject *SketchPy::getCustomAttributes(const char* /*attr*/) const
PyObject* SketchPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
@@ -211,5 +214,3 @@ int SketchPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -31,23 +31,21 @@
using namespace Sketcher;
//---------- Geometry Extension
TYPESYSTEM_SOURCE(Sketcher::SolverGeometryExtension,Part::GeometryExtension)
TYPESYSTEM_SOURCE(Sketcher::SolverGeometryExtension, Part::GeometryExtension)
SolverGeometryExtension::SolverGeometryExtension():
Start(SolverGeometryExtension::Dependent),
Mid(SolverGeometryExtension::Dependent),
End(SolverGeometryExtension::Dependent)
{
SolverGeometryExtension::SolverGeometryExtension()
: Start(SolverGeometryExtension::Dependent),
Mid(SolverGeometryExtension::Dependent),
End(SolverGeometryExtension::Dependent)
{}
}
void SolverGeometryExtension::copyAttributes(Part::GeometryExtension * cpy) const
void SolverGeometryExtension::copyAttributes(Part::GeometryExtension* cpy) const
{
Part::GeometryExtension::copyAttributes(cpy);
static_cast<SolverGeometryExtension *>(cpy)->Edge = this->Edge;
static_cast<SolverGeometryExtension *>(cpy)->Start = this->Start;
static_cast<SolverGeometryExtension *>(cpy)->End = this->End;
static_cast<SolverGeometryExtension *>(cpy)->Mid = this->Mid;
static_cast<SolverGeometryExtension*>(cpy)->Edge = this->Edge;
static_cast<SolverGeometryExtension*>(cpy)->Start = this->Start;
static_cast<SolverGeometryExtension*>(cpy)->End = this->End;
static_cast<SolverGeometryExtension*>(cpy)->Mid = this->Mid;
}
std::unique_ptr<Part::GeometryExtension> SolverGeometryExtension::copy() const
@@ -56,33 +54,35 @@ std::unique_ptr<Part::GeometryExtension> SolverGeometryExtension::copy() const
copyAttributes(cpy.get());
#if defined (__GNUC__) && (__GNUC__ <=4)
#if defined(__GNUC__) && (__GNUC__ <= 4)
return std::move(cpy);
#else
return cpy;
#endif
}
PyObject * SolverGeometryExtension::getPyObject()
PyObject* SolverGeometryExtension::getPyObject()
{
THROWM(Base::NotImplementedError, "SolverGeometryExtension does not have a Python counterpart");
}
SolverGeometryExtension::PointParameterStatus SolverGeometryExtension::getPoint(Sketcher::PointPos pos) const {
if(pos==Sketcher::PointPos::start)
SolverGeometryExtension::PointParameterStatus
SolverGeometryExtension::getPoint(Sketcher::PointPos pos) const
{
if (pos == Sketcher::PointPos::start)
return getStartPoint();
if(pos==Sketcher::PointPos::end)
if (pos == Sketcher::PointPos::end)
return getEndPoint();
if(pos==Sketcher::PointPos::mid)
if (pos == Sketcher::PointPos::mid)
return getMidPoint();
THROWM(Base::ValueError, "SolverGeometryExtension - getPoint: Edge is not a point");
}
void SolverGeometryExtension::notifyAttachment(Part::Geometry * geo)
void SolverGeometryExtension::notifyAttachment(Part::Geometry* geo)
{
// maps type to number of solver parameters taken by the edge
static std::map<Base::Type,int> edgeParamMap = {
static std::map<Base::Type, int> edgeParamMap = {
{Part::GeomPoint::getClassTypeId(), 0},
{Part::GeomLineSegment::getClassTypeId(), 0},
{Part::GeomArcOfCircle::getClassTypeId(), 3},
@@ -91,78 +91,80 @@ void SolverGeometryExtension::notifyAttachment(Part::Geometry * geo)
{Part::GeomEllipse::getClassTypeId(), 3},
{Part::GeomArcOfHyperbola::getClassTypeId(), 5},
{Part::GeomArcOfParabola::getClassTypeId(), 4},
{Part::GeomBSplineCurve::getClassTypeId(), 0} // is dynamic
{Part::GeomBSplineCurve::getClassTypeId(), 0}// is dynamic
};
GeometryType = geo->getTypeId();
auto result = edgeParamMap.find(GeometryType);
if( result == edgeParamMap.end() )
THROWM(Base::TypeError, "SolverGeometryExtension - notifyAttachment - Geometry not supported!!");
if (result == edgeParamMap.end())
THROWM(Base::TypeError,
"SolverGeometryExtension - notifyAttachment - Geometry not supported!!");
auto nedgeparams = (*result).second;
if(nedgeparams>0)
if (nedgeparams > 0)
Edge.init(nedgeparams);
}
void SolverGeometryExtension::ensureType(const Base::Type & type)
void SolverGeometryExtension::ensureType(const Base::Type& type)
{
if(GeometryType != type)
THROWM(Base::TypeError, "SolverGeometryExtension - requested edge parameters do not match underlying type!");
if (GeometryType != type)
THROWM(Base::TypeError,
"SolverGeometryExtension - requested edge parameters do not match underlying type!");
}
SolverGeometryExtension::Point & SolverGeometryExtension::getPoint()
SolverGeometryExtension::Point& SolverGeometryExtension::getPoint()
{
ensureType(Part::GeomPoint::getClassTypeId());
return static_cast<Point &>(Edge);
return static_cast<Point&>(Edge);
}
SolverGeometryExtension::Line & SolverGeometryExtension::getLine()
SolverGeometryExtension::Line& SolverGeometryExtension::getLine()
{
ensureType(Part::GeomLineSegment::getClassTypeId());
return static_cast<Line &>(Edge);
return static_cast<Line&>(Edge);
}
SolverGeometryExtension::Arc & SolverGeometryExtension::getArc()
SolverGeometryExtension::Arc& SolverGeometryExtension::getArc()
{
ensureType(Part::GeomArcOfCircle::getClassTypeId());
return static_cast<Arc &>(Edge);
return static_cast<Arc&>(Edge);
}
SolverGeometryExtension::Circle & SolverGeometryExtension::getCircle()
SolverGeometryExtension::Circle& SolverGeometryExtension::getCircle()
{
ensureType(Part::GeomCircle::getClassTypeId());
return static_cast<Circle &>(Edge);
return static_cast<Circle&>(Edge);
}
SolverGeometryExtension::ArcOfEllipse & SolverGeometryExtension::getArcOfEllipse()
SolverGeometryExtension::ArcOfEllipse& SolverGeometryExtension::getArcOfEllipse()
{
ensureType(Part::GeomArcOfEllipse::getClassTypeId());
return static_cast<ArcOfEllipse &>(Edge);
return static_cast<ArcOfEllipse&>(Edge);
}
SolverGeometryExtension::Ellipse & SolverGeometryExtension::getEllipse()
SolverGeometryExtension::Ellipse& SolverGeometryExtension::getEllipse()
{
ensureType(Part::GeomEllipse::getClassTypeId());
return static_cast<Ellipse &>(Edge);
return static_cast<Ellipse&>(Edge);
}
SolverGeometryExtension::ArcOfHyperbola & SolverGeometryExtension::getArcOfHyperbola()
SolverGeometryExtension::ArcOfHyperbola& SolverGeometryExtension::getArcOfHyperbola()
{
ensureType(Part::GeomArcOfHyperbola::getClassTypeId());
return static_cast<ArcOfHyperbola &>(Edge);
return static_cast<ArcOfHyperbola&>(Edge);
}
SolverGeometryExtension::ArcOfParabola & SolverGeometryExtension::getArcOfParabola()
SolverGeometryExtension::ArcOfParabola& SolverGeometryExtension::getArcOfParabola()
{
ensureType(Part::GeomArcOfParabola::getClassTypeId());
return static_cast<ArcOfParabola &>(Edge);
return static_cast<ArcOfParabola&>(Edge);
}
SolverGeometryExtension::BSpline & SolverGeometryExtension::getBSpline()
SolverGeometryExtension::BSpline& SolverGeometryExtension::getBSpline()
{
ensureType(Part::GeomBSplineCurve::getClassTypeId());
return static_cast<BSpline &>(Edge);
return static_cast<BSpline&>(Edge);
}

View File

@@ -33,55 +33,95 @@
namespace Sketcher
{
class SketcherExport SolverGeometryExtension : public Part::GeometryExtension
class SketcherExport SolverGeometryExtension: public Part::GeometryExtension
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
enum SolverStatus {
enum SolverStatus
{
FullyConstraint = 0,
NotFullyConstraint = 1,
NumSolverStatus
};
enum ParameterStatus {
enum ParameterStatus
{
Dependent = 0,
Independent = 1,
NumParameterStatus
};
class PointParameterStatus {
class PointParameterStatus
{
public:
explicit PointParameterStatus(ParameterStatus status) {setStatus(status);}
PointParameterStatus(ParameterStatus statusx, ParameterStatus statusy) {setStatus(statusx, statusy);}
explicit PointParameterStatus(ParameterStatus status)
{
setStatus(status);
}
PointParameterStatus(ParameterStatus statusx, ParameterStatus statusy)
{
setStatus(statusx, statusy);
}
PointParameterStatus(const PointParameterStatus &) = default;
PointParameterStatus & operator=(const PointParameterStatus &) = default;
PointParameterStatus(PointParameterStatus &&) = default;
PointParameterStatus & operator=(PointParameterStatus &&) = default;
PointParameterStatus(const PointParameterStatus&) = default;
PointParameterStatus& operator=(const PointParameterStatus&) = default;
PointParameterStatus(PointParameterStatus&&) = default;
PointParameterStatus& operator=(PointParameterStatus&&) = default;
ParameterStatus getStatus() const { return (xstatus == Independent && ystatus == Independent)?Independent:Dependent;}
ParameterStatus getStatusx() const { return xstatus;}
ParameterStatus getStatusy() const { return ystatus;}
ParameterStatus getStatus() const
{
return (xstatus == Independent && ystatus == Independent) ? Independent : Dependent;
}
ParameterStatus getStatusx() const
{
return xstatus;
}
ParameterStatus getStatusy() const
{
return ystatus;
}
bool isXDoF() {return xstatus == Dependent;}
bool isYDoF() {return ystatus == Dependent;}
bool isXDoF()
{
return xstatus == Dependent;
}
bool isYDoF()
{
return ystatus == Dependent;
}
int getDoFs() {
int getDoFs()
{
bool xfree = isXDoF();
bool yfree = isYDoF();
if(xfree && yfree)
if (xfree && yfree)
return 2;
else if(xfree || yfree)
else if (xfree || yfree)
return 1;
else
return 0;
}
void setStatus(ParameterStatus status) {xstatus=status; ystatus=status;}
void setStatus(ParameterStatus statusx, ParameterStatus statusy) {xstatus=statusx; ystatus=statusy;}
void setStatusx(ParameterStatus statusx) {xstatus=statusx;}
void setStatusy(ParameterStatus statusy) {ystatus=statusy;}
void setStatus(ParameterStatus status)
{
xstatus = status;
ystatus = status;
}
void setStatus(ParameterStatus statusx, ParameterStatus statusy)
{
xstatus = statusx;
ystatus = statusy;
}
void setStatusx(ParameterStatus statusx)
{
xstatus = statusx;
}
void setStatusy(ParameterStatus statusy)
{
ystatus = statusy;
}
private:
ParameterStatus xstatus;
@@ -93,108 +133,192 @@ public:
public:
EdgeParameterStatus() = default;
void init(int nparams) { pstatus.resize(nparams, ParameterStatus::Dependent);}
ParameterStatus getStatus() const {
return std::all_of(pstatus.begin(), pstatus.end(), [](const auto & v){ return v == Independent;})?Independent:Dependent;
void init(int nparams)
{
pstatus.resize(nparams, ParameterStatus::Dependent);
}
void setStatus(ParameterStatus status) { std::fill(pstatus.begin(), pstatus.end(), status);}
ParameterStatus getStatus() const
{
return std::all_of(pstatus.begin(),
pstatus.end(),
[](const auto& v) {
return v == Independent;
})
? Independent
: Dependent;
}
void setStatus(int index, ParameterStatus status) {
if(index >= int(pstatus.size()))
pstatus.resize(index+1,ParameterStatus::Dependent);
void setStatus(ParameterStatus status)
{
std::fill(pstatus.begin(), pstatus.end(), status);
}
void setStatus(int index, ParameterStatus status)
{
if (index >= int(pstatus.size()))
pstatus.resize(index + 1, ParameterStatus::Dependent);
pstatus.at(index) = status;
};
protected:
std::vector<ParameterStatus> pstatus;
};
class Point : public EdgeParameterStatus
class Point: public EdgeParameterStatus
{
public:
Point() = default;
};
class Line : public EdgeParameterStatus
class Line: public EdgeParameterStatus
{
public:
Line() = default;
};
class Arc : public EdgeParameterStatus
class Arc: public EdgeParameterStatus
{
public:
Arc() = default;
ParameterStatus getRadiusStatus() const {return pstatus[0];}
ParameterStatus getStartParameter() const {return pstatus[1];}
ParameterStatus getEndParameter() const {return pstatus[2];}
ParameterStatus getRadiusStatus() const
{
return pstatus[0];
}
ParameterStatus getStartParameter() const
{
return pstatus[1];
}
ParameterStatus getEndParameter() const
{
return pstatus[2];
}
};
class Circle : public EdgeParameterStatus
class Circle: public EdgeParameterStatus
{
public:
Circle() = default;
ParameterStatus getRadiusStatus() const {return pstatus[0];}
bool isRadiusDoF() const {return pstatus[0] == Dependent;}
ParameterStatus getRadiusStatus() const
{
return pstatus[0];
}
bool isRadiusDoF() const
{
return pstatus[0] == Dependent;
}
};
class ArcOfEllipse : public EdgeParameterStatus
class ArcOfEllipse: public EdgeParameterStatus
{
public:
ArcOfEllipse() = default;
ParameterStatus getFocusXStatus() const {return pstatus[0];}
ParameterStatus getFocusYStatus() const {return pstatus[1];}
ParameterStatus getFocusMinorRadiusStatus() const {return pstatus[2];}
ParameterStatus getStartParameter() const {return pstatus[3];}
ParameterStatus getEndParameter() const {return pstatus[4];}
ParameterStatus getFocusXStatus() const
{
return pstatus[0];
}
ParameterStatus getFocusYStatus() const
{
return pstatus[1];
}
ParameterStatus getFocusMinorRadiusStatus() const
{
return pstatus[2];
}
ParameterStatus getStartParameter() const
{
return pstatus[3];
}
ParameterStatus getEndParameter() const
{
return pstatus[4];
}
bool isFocusDoF() const {return pstatus[0] == Dependent || pstatus[1] == Dependent;}
bool isMinorRadiusDoF() const {return (pstatus[2] == Dependent);}
bool isFocusDoF() const
{
return pstatus[0] == Dependent || pstatus[1] == Dependent;
}
bool isMinorRadiusDoF() const
{
return (pstatus[2] == Dependent);
}
};
class Ellipse : public EdgeParameterStatus
class Ellipse: public EdgeParameterStatus
{
public:
Ellipse() = default;
ParameterStatus getFocusXStatus() const {return pstatus[0];}
ParameterStatus getFocusYStatus() const {return pstatus[1];}
ParameterStatus getFocusMinorRadiusStatus() const {return pstatus[2];}
ParameterStatus getFocusXStatus() const
{
return pstatus[0];
}
ParameterStatus getFocusYStatus() const
{
return pstatus[1];
}
ParameterStatus getFocusMinorRadiusStatus() const
{
return pstatus[2];
}
bool isFocusDoF() const {return pstatus[0] == Dependent || pstatus[1] == Dependent;}
bool isMinorRadiusDoF() const {return (pstatus[2] == Dependent);}
bool isFocusDoF() const
{
return pstatus[0] == Dependent || pstatus[1] == Dependent;
}
bool isMinorRadiusDoF() const
{
return (pstatus[2] == Dependent);
}
};
class ArcOfHyperbola : public EdgeParameterStatus
class ArcOfHyperbola: public EdgeParameterStatus
{
public:
ArcOfHyperbola() = default;
ParameterStatus getFocusXStatus() const {return pstatus[0];}
ParameterStatus getFocusYStatus() const {return pstatus[1];}
ParameterStatus getFocusMinorRadiusStatus() const {return pstatus[2];}
ParameterStatus getStartParameter() const {return pstatus[3];}
ParameterStatus getEndParameter() const {return pstatus[4];}
ParameterStatus getFocusXStatus() const
{
return pstatus[0];
}
ParameterStatus getFocusYStatus() const
{
return pstatus[1];
}
ParameterStatus getFocusMinorRadiusStatus() const
{
return pstatus[2];
}
ParameterStatus getStartParameter() const
{
return pstatus[3];
}
ParameterStatus getEndParameter() const
{
return pstatus[4];
}
};
class ArcOfParabola : public EdgeParameterStatus
class ArcOfParabola: public EdgeParameterStatus
{
public:
ArcOfParabola() = default;
ParameterStatus getFocusXStatus() const {return pstatus[0];}
ParameterStatus getFocusYStatus() const {return pstatus[1];}
ParameterStatus getFocusXStatus() const
{
return pstatus[0];
}
ParameterStatus getFocusYStatus() const
{
return pstatus[1];
}
};
class BSpline : public EdgeParameterStatus
class BSpline: public EdgeParameterStatus
{
public:
BSpline() = default;
@@ -203,30 +327,28 @@ public:
{
int npoles = pstatus.size() / 3;
if(poleindex < npoles)
return pstatus[poleindex*2];
if (poleindex < npoles)
return pstatus[poleindex * 2];
THROWM(Base::IndexError, "Pole index out of range")
}
ParameterStatus getPoleYStatus(int poleindex) const
{
int npoles = pstatus.size() / 3;
if(poleindex < npoles)
return pstatus[poleindex*2+1];
if (poleindex < npoles)
return pstatus[poleindex * 2 + 1];
THROWM(Base::IndexError, "Pole index out of range")
}
ParameterStatus getWeightStatus(int weightindex) const
{
int nweights = pstatus.size() / 3;
if(weightindex < nweights)
return pstatus[nweights*2 + weightindex];
if (weightindex < nweights)
return pstatus[nweights * 2 + weightindex];
THROWM(Base::IndexError, "Weight index out of range")
}
@@ -238,51 +360,112 @@ public:
std::unique_ptr<Part::GeometryExtension> copy() const override;
PyObject *getPyObject() override;
PyObject* getPyObject() override;
void notifyAttachment(Part::Geometry * geo) override;
void notifyAttachment(Part::Geometry* geo) override;
SolverStatus getGeometry() const {return ( Edge.getStatus() == Independent &&
Start.getStatus() == Independent &&
End.getStatus() == Independent &&
Mid.getStatus() == Independent) ? FullyConstraint : NotFullyConstraint;}
SolverStatus getGeometry() const
{
return (Edge.getStatus() == Independent && Start.getStatus() == Independent
&& End.getStatus() == Independent && Mid.getStatus() == Independent)
? FullyConstraint
: NotFullyConstraint;
}
ParameterStatus getEdge() const {return Edge.getStatus();}
Point & getPoint();
Line & getLine();
Arc & getArc();
Circle & getCircle();
ArcOfEllipse & getArcOfEllipse();
Ellipse & getEllipse();
ArcOfHyperbola & getArcOfHyperbola();
ArcOfParabola & getArcOfParabola();
BSpline & getBSpline();
EdgeParameterStatus getEdgeParameters() {return Edge;}
void setEdge(ParameterStatus status) {Edge.setStatus(status);}
void setEdge(int paramindex, ParameterStatus status) {Edge.setStatus(paramindex,status);}
ParameterStatus getEdge() const
{
return Edge.getStatus();
}
Point& getPoint();
Line& getLine();
Arc& getArc();
Circle& getCircle();
ArcOfEllipse& getArcOfEllipse();
Ellipse& getEllipse();
ArcOfHyperbola& getArcOfHyperbola();
ArcOfParabola& getArcOfParabola();
BSpline& getBSpline();
EdgeParameterStatus getEdgeParameters()
{
return Edge;
}
void setEdge(ParameterStatus status)
{
Edge.setStatus(status);
}
void setEdge(int paramindex, ParameterStatus status)
{
Edge.setStatus(paramindex, status);
}
ParameterStatus getStart() const {return Start.getStatus();}
PointParameterStatus getStartPoint() const {return Start;}
void setStart(ParameterStatus xstatus, ParameterStatus ystatus) {Start.setStatus(xstatus,ystatus);}
void setStartx(ParameterStatus xstatus) {Start.setStatusx(xstatus);}
void setStarty(ParameterStatus ystatus) {Start.setStatusy(ystatus);}
ParameterStatus getStart() const
{
return Start.getStatus();
}
PointParameterStatus getStartPoint() const
{
return Start;
}
void setStart(ParameterStatus xstatus, ParameterStatus ystatus)
{
Start.setStatus(xstatus, ystatus);
}
void setStartx(ParameterStatus xstatus)
{
Start.setStatusx(xstatus);
}
void setStarty(ParameterStatus ystatus)
{
Start.setStatusy(ystatus);
}
ParameterStatus getMid() const {return Mid.getStatus();}
PointParameterStatus getMidPoint() const {return Mid;}
void setMid(ParameterStatus xstatus, ParameterStatus ystatus) {Mid.setStatus(xstatus,ystatus);}
void setMidx(ParameterStatus xstatus) {Mid.setStatusx(xstatus);}
void setMidy(ParameterStatus ystatus) {Mid.setStatusy(ystatus);}
ParameterStatus getMid() const
{
return Mid.getStatus();
}
PointParameterStatus getMidPoint() const
{
return Mid;
}
void setMid(ParameterStatus xstatus, ParameterStatus ystatus)
{
Mid.setStatus(xstatus, ystatus);
}
void setMidx(ParameterStatus xstatus)
{
Mid.setStatusx(xstatus);
}
void setMidy(ParameterStatus ystatus)
{
Mid.setStatusy(ystatus);
}
ParameterStatus getEnd() const {return End.getStatus();}
PointParameterStatus getEndPoint() const {return End;}
ParameterStatus getEnd() const
{
return End.getStatus();
}
PointParameterStatus getEndPoint() const
{
return End;
}
void setEnd(ParameterStatus xstatus, ParameterStatus ystatus) {End.setStatus(xstatus,ystatus);}
void setEndx(ParameterStatus xstatus) {End.setStatusx(xstatus);}
void setEndy(ParameterStatus ystatus) {End.setStatusy(ystatus);}
void setEnd(ParameterStatus xstatus, ParameterStatus ystatus)
{
End.setStatus(xstatus, ystatus);
}
void setEndx(ParameterStatus xstatus)
{
End.setStatusx(xstatus);
}
void setEndy(ParameterStatus ystatus)
{
End.setStatusy(ystatus);
}
PointParameterStatus getPoint(Sketcher::PointPos pos) const;
void init(ParameterStatus status) {
void init(ParameterStatus status)
{
Edge.setStatus(status);
Start.setStatus(status);
Mid.setStatus(status);
@@ -290,24 +473,24 @@ public:
}
protected:
void copyAttributes(Part::GeometryExtension * cpy) const override;
void copyAttributes(Part::GeometryExtension* cpy) const override;
private:
SolverGeometryExtension(const SolverGeometryExtension&) = default;
void ensureType(const Base::Type & type);
void ensureType(const Base::Type& type);
private:
EdgeParameterStatus Edge;
EdgeParameterStatus Edge;
PointParameterStatus Start;
PointParameterStatus Mid;
PointParameterStatus End;
PointParameterStatus Start;
PointParameterStatus Mid;
PointParameterStatus End;
Base::Type GeometryType;
Base::Type GeometryType;
};
} //namespace Sketcher
}// namespace Sketcher
#endif // SKETCHER_SOLVERGEOMETRYEXTENSION_H
#endif// SKETCHER_SOLVERGEOMETRYEXTENSION_H