[Sketcher] Create SketchObject::buildShape()

Needs changes in TopoShape and creation of ExternalGeometryFacade.

Also contains the squashed ticket:

[Sketcher] Hide unimplemented code

These will eventually be implemented in phase 3 of toponaming.

[Sketcher] Implement trivial `checkSubName` to appease Windows

[Sketcher] Modify `GeoEnum` usage
This commit is contained in:
Ajinkya Dahale
2023-05-30 10:20:56 +05:30
committed by Chris Hennes
parent de6f33f004
commit a52bc93da0
3 changed files with 243 additions and 36 deletions

View File

@@ -68,7 +68,7 @@ enum GeoEnum
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)
GeoUndef = -2000// GeoId of an undefined Geometry (uninitialised or unused GeoId)
};
/*!

View File

@@ -44,6 +44,7 @@
#include <Geom_TrimmedCurve.hxx>
#include <Standard_Version.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
@@ -57,11 +58,16 @@
#include <gp_Pln.hxx>
#endif
#include <boost/algorithm/string/predicate.hpp>
#include <App/Application.h>
#include <App/Document.h>
#include <App/ElementNamingUtils.h>
#include <App/Expression.h>
#include <App/ExpressionParser.h>
#include <App/FeaturePythonPyImp.h>
#include <App/IndexedName.h>
#include <App/MappedName.h>
#include <App/ObjectIdentifier.h>
#include <App/OriginFeature.h>
#include <App/Part.h>
@@ -73,6 +79,7 @@
#include <Mod/Part/App/BodyBase.h>
#include <Mod/Part/App/DatumFeature.h>
#include <Mod/Part/App/GeometryMigrationExtension.h>
#include <Mod/Part/App/TopoShapeOpCode.h>
#include "SketchObject.h"
#include "SketchObjectPy.h"
@@ -238,6 +245,64 @@ App::DocumentObjectExecReturn* SketchObject::execute()
return App::DocumentObject::StdReturn;
}
void SketchObject::buildShape()
{
// Shape.setValue(solvedSketch.toShape());
// We use the following instead to map element names
std::vector<Part::TopoShape> shapes;
std::vector<Part::TopoShape> vertices;
int i=0;
for(auto geo : getInternalGeometry()) {
++i;
if(GeometryFacade::getConstruction(geo))
continue;
if (geo->isDerivedFrom(Part::GeomPoint::getClassTypeId())) {
vertices.emplace_back(TopoDS::Vertex(geo->toShape()));
int idx = getVertexIndexGeoPos(i-1, PointPos::start);
std::string name = convertSubName(Data::IndexedName::fromConst("Vertex", idx+1), false);
// vertices.back().setElementName(Data::IndexedName::fromConst("Vertex", 1),
// Data::MappedName::fromRawData(name.c_str()));
} else
shapes.push_back(getEdge(geo,convertSubName(
Data::IndexedName::fromConst("Edge", i), false).c_str()));
}
// FIXME: Commented since ExternalGeometryFacade is not added
// for(i=2;i<ExternalGeo.getSize();++i) {
// auto geo = ExternalGeo[i];
// auto egf = ExternalGeometryFacade::getFacade(geo);
// if(!egf->testFlag(ExternalGeometryExtension::Defining))
// continue;
// shapes.push_back(getEdge(geo, convertSubName(
// Data::IndexedName::fromConst("ExternalEdge", i-1), false).c_str()));
// }
// if(shapes.empty() && vertices.empty())
// Shape.setValue(Part::TopoShape());
// else if (vertices.empty()) {
// // Notice here we supply op code Part::OpCodes::Sketch to makEWires().
// Shape.setValue(Part::TopoShape().makEWires(shapes,Part::OpCodes::Sketch));
// } else {
// std::vector<Part::TopoShape> results;
// if (!shapes.empty()) {
// // This call of makEWires() does not have the op code, in order to
// // avoid duplication. Because we'll going to make a compound (to
// // include the vertices) below with the same op code.
// //
// // Note, that we HAVE TO add the Part::OpCodes::Sketch op code to all
// // geometry exposed through the Shape property, because
// // SketchObject::getElementName() relies on this op code to
// // differentiate geometries that are exposed with those in edit
// // mode.
// auto wires = Part::TopoShape().makEWires(shapes);
// for (const auto &wire : wires.getSubTopoShapes(TopAbs_WIRE))
// results.push_back(wire);
// }
// results.insert(results.end(), vertices.begin(), vertices.end());
// Shape.setValue(Part::TopoShape().makECompound(results, Part::OpCodes::Sketch));
// }
}
int SketchObject::hasConflicts() const
{
if (lastDoF < 0)// over-constrained sketch
@@ -766,81 +831,81 @@ int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toP
return lastSolverStatus;
}
Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
Base::Vector3d SketchObject::getPoint(const Part::Geometry *geo, PointPos PosId)
{
if (!(GeoId == H_Axis || GeoId == V_Axis
|| (GeoId <= getHighestCurveIndex() && GeoId >= -getExternalGeometryCount())))
throw Base::ValueError("SketchObject::getPoint. Invalid GeoId was supplied.");
const Part::Geometry* geo = getGeometry(GeoId);
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 (PosId == PointPos::start || PosId == PointPos::mid || PosId == 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 (PosId == PointPos::start)
return lineSeg->getStartPoint();
else if (PosId == PointPos::end)
return lineSeg->getEndPoint();
}
else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle* circle = static_cast<const Part::GeomCircle*>(geo);
if (PosId == PointPos::mid)
return circle->getCenter();
}
else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
const Part::GeomEllipse* ellipse = static_cast<const Part::GeomEllipse*>(geo);
if (PosId == 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::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle = static_cast<const Part::GeomCircle*>(geo);
auto pt = circle->getCenter();
if(PosId != PointPos::mid)
pt.x += circle->getRadius();
return pt;
} else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
const Part::GeomEllipse *ellipse = static_cast<const Part::GeomEllipse*>(geo);
auto pt = ellipse->getCenter();
if(PosId != PointPos::mid)
pt += ellipse->getMajorAxisDir()*ellipse->getMajorRadius();
return pt;
} else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *aoc = static_cast<const Part::GeomArcOfCircle*>(geo);
if (PosId == PointPos::start)
return aoc->getStartPoint(/*emulateCCW=*/true);
else if (PosId == PointPos::end)
return aoc->getEndPoint(/*emulateCCW=*/true);
else if (PosId == 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 (PosId == PointPos::start)
return aoc->getStartPoint(/*emulateCCW=*/true);
else if (PosId == PointPos::end)
return aoc->getEndPoint(/*emulateCCW=*/true);
else if (PosId == 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 (PosId == PointPos::start)
return aoh->getStartPoint();
else if (PosId == PointPos::end)
return aoh->getEndPoint();
else if (PosId == 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 (PosId == PointPos::start)
return aop->getStartPoint();
else if (PosId == PointPos::end)
return aop->getEndPoint();
else if (PosId == 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 (PosId == PointPos::start)
return bsp->getStartPoint();
else if (PosId == PointPos::end)
return bsp->getEndPoint();
}
return Base::Vector3d();
}
Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
{
if (!(GeoId == H_Axis || GeoId == V_Axis
|| (GeoId <= getHighestCurveIndex() && GeoId >= -getExternalGeometryCount())))
throw Base::ValueError("SketchObject::getPoint. Invalid GeoId was supplied.");
const Part::Geometry* geo = getGeometry(GeoId);
return getPoint(geo,PosId);
}
int SketchObject::getAxisCount() const
{
const std::vector<Part::Geometry*>& vals = getInternalGeometry();
@@ -9262,6 +9327,115 @@ void SketchObject::setExpression(const App::ObjectIdentifier& path,
}
}
Part::TopoShape SketchObject::getEdge(const Part::Geometry *geo, const char *name) const
{
Part::TopoShape shape(geo->toShape());
// shape.setElementName(Data::IndexedName::fromConst("Edge", 1),
// Data::MappedName::fromRawData(name));
TopTools_IndexedMapOfShape vmap;
TopExp::MapShapes(shape.getShape(), TopAbs_VERTEX, vmap);
std::ostringstream ss;
for(int i=1;i<=vmap.Extent();++i) {
auto gpt = BRep_Tool::Pnt(TopoDS::Vertex(vmap(i)));
Base::Vector3d pt(gpt.X(),gpt.Y(),gpt.Z());
PointPos pos[] = {PointPos::start,PointPos::end};
for(size_t j=0;j<sizeof(pos)/sizeof(pos[0]);++j) {
if(getPoint(geo,pos[j]) == pt) {
ss.str("");
ss << name << 'v' << static_cast<int>(pos[j]);
// shape.setElementName(Data::IndexedName::fromConst("Vertex", i),
// Data::MappedName::fromRawData(ss.str().c_str()));
break;
}
}
}
return shape;
}
Data::IndexedName SketchObject::checkSubName(const char *sub) const
{
// FIXME: trivial implementation needs to be replaced with full logic
(void)sub;
return Data::IndexedName();
}
bool SketchObject::geoIdFromShapeType(const Data::IndexedName & indexedName,
int &geoId,
PointPos &posId) const
{
posId = PointPos::none;
geoId = Sketcher::GeoEnum::GeoUndef;
if (!indexedName)
return false;
const char *shapetype = indexedName.getType();
if (boost::equals(shapetype,"Edge") ||
boost::equals(shapetype,"edge")) {
geoId = indexedName.getIndex() - 1;
} else if (boost::equals(shapetype,"ExternalEdge")) {
geoId = indexedName.getIndex() - 1;
geoId = Sketcher::GeoEnum::RefExt - geoId;
} else if (boost::equals(shapetype,"Vertex") ||
boost::equals(shapetype,"vertex")) {
int VtId = indexedName.getIndex() - 1;
getGeoVertexIndex(VtId,geoId,posId);
if (posId==PointPos::none) return false;
} else if (boost::equals(shapetype,"H_Axis")) {
geoId = Sketcher::GeoEnum::HAxis;
} else if (boost::equals(shapetype,"V_Axis")) {
geoId = Sketcher::GeoEnum::VAxis;
} else if (boost::equals(shapetype,"RootPoint")) {
geoId = Sketcher::GeoEnum::RtPnt;
posId = PointPos::start;
} else
return false;
return true;
}
std::string SketchObject::convertSubName(const Data::IndexedName & indexedName, bool postfix) const
{
std::ostringstream ss;
int geoId;
PointPos posId;
if(!geoIdFromShapeType(indexedName,geoId,posId)) {
ss << indexedName;
return ss.str();
}
if(geoId == Sketcher::GeoEnum::HAxis ||
geoId == Sketcher::GeoEnum::VAxis ||
geoId == Sketcher::GeoEnum::RtPnt) {
if (postfix)
ss << Data::ELEMENT_MAP_PREFIX;
ss << indexedName;
if(postfix)
ss << '.' << indexedName;
return ss.str();
}
auto geo = getGeometry(geoId);
if(!geo) {
std::string res = indexedName.toString();
return res;
}
if (postfix)
ss << Data::ELEMENT_MAP_PREFIX;
ss << (geoId>=0?'g':'e') << GeometryFacade::getFacade(geo)->getId();
if(posId!=PointPos::none)
ss << 'v' << static_cast<int>(posId);
if(postfix) {
// rename Edge to edge, and Vertex to vertex to avoid ambiguous of
// element mapping of the public shape and internal geometry.
if (indexedName.getIndex() <= 0)
ss << '.' << indexedName;
else if(boost::starts_with(indexedName.getType(),"Edge"))
ss << ".e" << (indexedName.getType()+1) << indexedName.getIndex();
else if(boost::starts_with(indexedName.getType(),"Vertex"))
ss << ".v" << (indexedName.getType()+1) << indexedName.getIndex();
else
ss << '.' << indexedName;
}
return ss.str();
}
int SketchObject::autoConstraint(double precision, double angleprecision, bool includeconstruction)
{
return analyser->autoconstraint(precision, angleprecision, includeconstruction);

View File

@@ -24,6 +24,7 @@
#define SKETCHER_SKETCHOBJECT_H
#include <App/FeaturePython.h>
#include <App/IndexedName.h>
#include <App/PropertyFile.h>
#include <Base/Axis.h>
#include <Mod/Part/App/Part2DObject.h>
@@ -272,6 +273,7 @@ public:
int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative = false,
bool updateGeoBeforeMoving = false);
/// retrieves the coordinates of a point
static Base::Vector3d getPoint(const Part::Geometry *geo, PointPos PosId);
Base::Vector3d getPoint(int GeoId, PointPos PosId) const;
/// toggle geometry to draft line
@@ -597,6 +599,35 @@ public:
bool isCarbonCopyAllowed(App::Document* pDoc, App::DocumentObject* pObj, bool& xinv, bool& yinv,
eReasonList* rsn = nullptr) const;
Part::TopoShape getEdge(const Part::Geometry *geo, const char *name) const;
Data::IndexedName checkSubName(const char *sub) const;
bool geoIdFromShapeType(const Data::IndexedName &, int &geoId, PointPos &posId) const;
bool geoIdFromShapeType(const char *shapetype, int &geoId, PointPos &posId) const
{
return geoIdFromShapeType(checkSubName(shapetype), geoId, posId);
}
bool geoIdFromShapeType(const char *shapetype, int &geoId) const
{
PointPos posId;
return geoIdFromShapeType(shapetype,geoId,posId);
}
std::string convertSubName(const char *subname, bool postfix=true) const
{
return convertSubName(checkSubName(subname), postfix);
}
std::string convertSubName(const std::string & subname, bool postfix=true) const
{
return convertSubName(subname.c_str(), postfix);
}
std::string convertSubName(const Data::IndexedName &, bool postfix=true) const;
bool isPerformingInternalTransaction() const
{
return internaltransaction;
@@ -654,6 +685,8 @@ protected:
void onDocumentRestored() override;
void restoreFinished() override;
void buildShape();
void setExpression(const App::ObjectIdentifier& path,
std::shared_ptr<App::Expression> expr) override;