Allow creating a datum plane tangential to a cylinder and parallel to another plane
This commit is contained in:
committed by
Stefan Tröger
parent
a0ec4752d9
commit
34acc5f8b4
@@ -34,8 +34,10 @@
|
||||
# include <gp_GTrsf.hxx>
|
||||
# include <gp_Lin.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <gp_Cylinder.hxx>
|
||||
# include <Geom_Line.hxx>
|
||||
# include <Geom_Plane.hxx>
|
||||
# include <Geom_CylindricalSurface.hxx>
|
||||
# include <Geom2d_Line.hxx>
|
||||
# include <Handle_Geom_Curve.hxx>
|
||||
# include <Handle_Geom_Surface.hxx>
|
||||
@@ -74,6 +76,7 @@ using namespace PartDesign;
|
||||
|
||||
// Note: We don't distinguish between e.g. datum lines and edges here
|
||||
#define PLANE QObject::tr("DPLANE")
|
||||
#define CYLINDER QObject::tr("DCYLINDER")
|
||||
#define LINE QObject::tr("DLINE")
|
||||
#define POINT QObject::tr("DPOINT")
|
||||
#define ANGLE QObject::tr("Angle")
|
||||
@@ -132,6 +135,15 @@ void Plane::initHints()
|
||||
key.insert(LINE); key.insert(PLANE); key.insert(ANGLE);
|
||||
hints[key] = DONE; // {LINE, PLANE, ANGLE} -> DONE. Plane through line with angle to other plane
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(CYLINDER);
|
||||
value.insert(PLANE);
|
||||
hints[key] = value; // CYLINDER -> PLANE
|
||||
|
||||
key.clear(); value.clear();
|
||||
key.insert(CYLINDER); key.insert(PLANE);
|
||||
hints[key] = DONE; // {CYLINDER, PLANE} -> DONE. Plane tangential to cylinder and normal to other plane
|
||||
|
||||
key.clear(); value.clear();
|
||||
value.insert(POINT); value.insert(LINE); value.insert(PLANE); value.insert(ANGLE);
|
||||
hints[key] = value;
|
||||
@@ -188,6 +200,7 @@ void Plane::onChanged(const App::Property *prop)
|
||||
Base::Vector3d* p3 = NULL;
|
||||
Base::Vector3d* normal = NULL;
|
||||
gp_Lin* line = NULL;
|
||||
gp_Cylinder* cyl = NULL;
|
||||
|
||||
for (int i = 0; i < refs.size(); i++) {
|
||||
if (refs[i]->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId())) {
|
||||
@@ -246,30 +259,33 @@ void Plane::onChanged(const App::Property *prop)
|
||||
} else if (subshape.ShapeType() == TopAbs_FACE) {
|
||||
TopoDS_Face f = TopoDS::Face(subshape);
|
||||
BRepAdaptor_Surface adapt(f);
|
||||
if (adapt.GetType() != GeomAbs_Plane)
|
||||
return; // Non-planar face
|
||||
if (adapt.GetType() == GeomAbs_Plane) {
|
||||
// Ensure that the front and back of the plane corresponds with the face's idea of front and back
|
||||
bool reverse = (f.Orientation() == TopAbs_REVERSED);
|
||||
gp_Pln plane = adapt.Plane();
|
||||
if (!plane.Direct()) {
|
||||
// toggle if plane has a left-handed coordinate system
|
||||
plane.UReverse();
|
||||
reverse = !reverse;
|
||||
}
|
||||
gp_Dir d = adapt.Plane().Axis().Direction();
|
||||
if (reverse) d.Reverse();
|
||||
|
||||
// Ensure that the front and back of the plane corresponds with the face's idea of front and back
|
||||
bool reverse = (f.Orientation() == TopAbs_REVERSED);
|
||||
gp_Pln plane = adapt.Plane();
|
||||
if (!plane.Direct()) {
|
||||
// toggle if plane has a left-handed coordinate system
|
||||
plane.UReverse();
|
||||
reverse = !reverse;
|
||||
// Ensure that the position of the placement corresponds to what the face would yield in
|
||||
// Part2DObject::positionBySupport()
|
||||
Base::Vector3d pos = feature->Placement.getValue().getPosition();
|
||||
gp_Pnt gp_pos(pos.x,pos.y,pos.z);
|
||||
Handle (Geom_Plane) gPlane = new Geom_Plane(plane);
|
||||
GeomAPI_ProjectPointOnSurf projector(gp_pos,gPlane);
|
||||
gp_Pnt b = projector.NearestPoint();
|
||||
|
||||
p1 = new Base::Vector3d(b.X(), b.Y(), b.Z());
|
||||
normal = new Base::Vector3d(d.X(), d.Y(), d.Z());
|
||||
} else if (adapt.GetType() == GeomAbs_Cylinder) {
|
||||
cyl = new gp_Cylinder(adapt.Cylinder());
|
||||
} else {
|
||||
return; // invalid surface type
|
||||
}
|
||||
gp_Dir d = adapt.Plane().Axis().Direction();
|
||||
if (reverse) d.Reverse();
|
||||
|
||||
// Ensure that the position of the placement corresponds to what the face would yield in
|
||||
// Part2DObject::positionBySupport()
|
||||
Base::Vector3d pos = feature->Placement.getValue().getPosition();
|
||||
gp_Pnt gp_pos(pos.x,pos.y,pos.z);
|
||||
Handle (Geom_Plane) gPlane = new Geom_Plane(plane);
|
||||
GeomAPI_ProjectPointOnSurf projector(gp_pos,gPlane);
|
||||
gp_Pnt b = projector.NearestPoint();
|
||||
|
||||
p1 = new Base::Vector3d(b.X(), b.Y(), b.Z());
|
||||
normal = new Base::Vector3d(d.X(), d.Y(), d.Z());
|
||||
}
|
||||
} else {
|
||||
return; //"PartDesign::Plane: Invalid reference type"
|
||||
@@ -284,6 +300,22 @@ void Plane::onChanged(const App::Property *prop)
|
||||
gp_Dir dir = line->Direction();
|
||||
Base::Rotation rot(Base::Vector3d(dir.X(), dir.Y(), dir.Z()), Angle.getValue() / 180.0 * M_PI);
|
||||
rot.multVec(*normal, *normal);
|
||||
} else if ((cyl != NULL) && (normal != NULL)) {
|
||||
// Plane tangential to cylinder and parallel to other plane
|
||||
gp_Dir dir(normal->x, normal->y, normal->z);
|
||||
Handle_Geom_Curve normalLine = new Geom_Line(cyl->Location(), dir);
|
||||
Handle_Geom_Surface cylinder = new Geom_CylindricalSurface(*cyl);
|
||||
|
||||
// Intersect a line through the base point of the cylinder and normal to the plane with the cylinder itself
|
||||
GeomAPI_IntCS intersector(normalLine, cylinder);
|
||||
if (!intersector.IsDone() || (intersector.NbPoints() == 0))
|
||||
return;
|
||||
if (intersector.NbPoints() > 1)
|
||||
Base::Console().Warning("More than one intersection point for datum plane from cylinder and plane");
|
||||
|
||||
gp_Pnt inter = intersector.Point(1);
|
||||
p1 = new Base::Vector3d(inter.X(), inter.Y(), inter.Z());
|
||||
// TODO: Allow to control which side of the cylinder the plane is create on - there are always two possibilities
|
||||
} else if ((p1 != NULL) && (normal != NULL)) {
|
||||
// plane from other plane. Nothing to be done
|
||||
} else if ((p1 != NULL) && (p2 != NULL) && (p3 != NULL)) {
|
||||
@@ -315,6 +347,7 @@ void Plane::onChanged(const App::Property *prop)
|
||||
if (p2 != NULL) delete p2;
|
||||
if (p3 != NULL) delete p3;
|
||||
if (line != NULL) delete line;
|
||||
if (cyl != NULL) delete cyl;
|
||||
}
|
||||
|
||||
Part::Datum::onChanged(prop);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
# include <gp_Pln.hxx>
|
||||
# include <Geom_Line.hxx>
|
||||
# include <Geom_Plane.hxx>
|
||||
# include <Geom_CylindricalSurface.hxx>
|
||||
# include <Geom2d_Line.hxx>
|
||||
# include <Handle_Geom_Curve.hxx>
|
||||
# include <Handle_Geom_Surface.hxx>
|
||||
@@ -73,6 +74,7 @@ using namespace PartDesign;
|
||||
|
||||
// Note: We don't distinguish between e.g. datum lines and edges here
|
||||
#define PLANE QObject::tr("DPLANE")
|
||||
#define CYLINDER QObject::tr("DCYLINDER")
|
||||
#define LINE QObject::tr("DLINE")
|
||||
#define POINT QObject::tr("DPOINT")
|
||||
#define ANGLE QObject::tr("Angle")
|
||||
@@ -317,14 +319,26 @@ const QString getRefType(const App::DocumentObject* obj, const std::string& subn
|
||||
return LINE;
|
||||
else if (type == PartDesign::Point::getClassTypeId())
|
||||
return POINT;
|
||||
else if (type.isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
// Note: For now, only planar references are possible
|
||||
if (subname.size() > 4 && subname.substr(0,4) == "Face")
|
||||
return PLANE;
|
||||
else if (subname.size() > 4 && subname.substr(0,4) == "Edge")
|
||||
else if (type.isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
if (subname.size() > 4 && subname.substr(0,4) == "Face") {
|
||||
const Part::Feature* feature = static_cast<const Part::Feature*>(obj);
|
||||
Part::TopoShape topShape = feature->Shape.getShape();
|
||||
TopoDS_Shape shape = topShape.getSubShape(subname.c_str());
|
||||
if (shape.IsNull() || (shape.ShapeType() != TopAbs_FACE))
|
||||
throw Base::Exception("Part::Datum::getRefType(): No valid subshape could be extracted");
|
||||
BRepAdaptor_Surface adapt(TopoDS::Face(shape));
|
||||
if (adapt.GetType() == GeomAbs_Plane)
|
||||
return PLANE;
|
||||
else if (adapt.GetType() == GeomAbs_Cylinder)
|
||||
return CYLINDER;
|
||||
else
|
||||
throw Base::Exception("Part::Datum::getRefType(): Only planar and cylindrical faces are allowed");
|
||||
} else if (subname.size() > 4 && subname.substr(0,4) == "Edge") {
|
||||
// Note: For now, only linear references are possible
|
||||
return LINE;
|
||||
else if (subname.size() > 6 && subname.substr(0,6) == "Vertex")
|
||||
} else if (subname.size() > 6 && subname.substr(0,6) == "Vertex") {
|
||||
return POINT;
|
||||
}
|
||||
}
|
||||
|
||||
throw Base::Exception("Part::Datum::getRefType(): Illegal object type");
|
||||
|
||||
@@ -58,6 +58,8 @@ bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, c
|
||||
|
||||
if (pObj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) {
|
||||
// Allow selecting Part::Datum features from the active Body
|
||||
if (ActivePartObject == NULL)
|
||||
return false;
|
||||
if (!ActivePartObject->hasFeature(pObj))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -184,6 +184,8 @@ const QString makeRefText(std::set<QString> hint)
|
||||
tText = QObject::tr("Line");
|
||||
else if (((*t) == QObject::tr("DPOINT")) || ((*t) == QObject::tr("Point")))
|
||||
tText = QObject::tr("Point");
|
||||
else if (((*t) == QObject::tr("DCYLINDER")) || ((*t) == QObject::tr("Cylinder")))
|
||||
tText = QObject::tr("Cylinder");
|
||||
else if ((*t) == QObject::tr("Done"))
|
||||
tText = QObject::tr("Done");
|
||||
result += QString::fromAscii(result.size() == 0 ? "" : "/") + tText;
|
||||
|
||||
Reference in New Issue
Block a user