Add ParallelPlane attachment mode.

It results in an attachment similar to ObjectXY but with the XY plane translated to pass through a selected vertex.

It is most useful to place sketches: pick a plane (XY, XZ, YZ) or another sketch then select a vertex to automatically translate the sketch in the Z-direction. In contrast to the Translate mode it does not change the origin.
This commit is contained in:
Mihail Dumitrescu
2024-05-29 16:48:30 +03:00
committed by Chris Hennes
parent 3a84e03f89
commit 0346c94b50
4 changed files with 50 additions and 2 deletions

View File

@@ -31,6 +31,7 @@
# include <BRepGProp.hxx>
# include <BRepIntCurveSurface_Inter.hxx>
# include <BRepLProp_SLProps.hxx>
# include <Geom_Line.hxx>
# include <Geom_Plane.hxx>
# include <GeomAdaptor.hxx>
# include <GeomAPI.hxx>
@@ -133,6 +134,8 @@ const char* AttachEngine::eMapModeStrings[]= {
"OYZ",
"OYX",
"ParallelPlane",
nullptr};
//this list must be in sync with eRefType enum.
@@ -1041,6 +1044,11 @@ AttachEngine3D::AttachEngine3D()
modeRefTypes[mmObjectXZ] = ss;
modeRefTypes[mmObjectYZ] = ss;
modeRefTypes[mmParallelPlane].push_back(
cat(eRefType(rtFlatFace | rtFlagHasPlacement), rtVertex));
modeRefTypes[mmParallelPlane].push_back(
cat(eRefType(rtAnything | rtFlagHasPlacement), rtVertex));
modeRefTypes[mmInertialCS].push_back(cat(rtAnything));
modeRefTypes[mmInertialCS].push_back(cat(rtAnything,rtAnything));
modeRefTypes[mmInertialCS].push_back(cat(rtAnything,rtAnything,rtAnything));
@@ -1194,7 +1202,8 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
} break;
case mmObjectXY:
case mmObjectXZ:
case mmObjectYZ: {
case mmObjectYZ:
case mmParallelPlane: {
// DeepSOIC: could have been done much more efficiently, but I'm lazy...
gp_Dir dirX, dirY, dirZ;
if (types[0] & rtFlagHasPlacement) {
@@ -1254,6 +1263,32 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
SketchNormal = dirX;
SketchXAxis = gp_Vec(dirY);
break;
case mmParallelPlane: {
if (shapes.size() < 2) {
throw Base::ValueError("AttachEngine3D::calculateAttachedPlacement: not "
"enough subshapes (need one plane and one vertex).");
}
TopoDS_Vertex vertex;
try {
vertex = TopoDS::Vertex(*(shapes[1]));
}
catch (...) {
}
if (vertex.IsNull()) {
throw Base::ValueError(
"Null vertex in AttachEngine3D::calculateAttachedPlacement()!");
}
SketchNormal = dirZ;
SketchXAxis = gp_Vec(dirX);
// The new origin will be the vertex projected onto the normal.
Handle(Geom_Line) hCurve(new Geom_Line(SketchBasePoint, dirZ));
gp_Pnt p = BRep_Tool::Pnt(vertex);
GeomAPI_ProjectPointOnCurve projector(p, hCurve);
SketchBasePoint = projector.NearestPoint();
} break;
default:
break;
}
@@ -1360,7 +1395,7 @@ AttachEngine3D::_calculateAttachedPlacement(const std::vector<App::DocumentObjec
case mmTangentPlane: {
if (shapes.size() < 2) {
throw Base::ValueError("AttachEngine3D::calculateAttachedPlacement: not enough "
"subshapes (need one false and one vertex).");
"subshapes (need one face and one vertex).");
}
bool bThruVertex = false;

View File

@@ -107,6 +107,8 @@ enum eMapMode {
mmOYZ,
mmOYX,
mmParallelPlane,
mmDummy_NumberOfModes//a value useful to check the validity of mode value
};//see also eMapModeStrings[] definition in .cpp

View File

@@ -63,6 +63,9 @@ TextSet getUIStrings(Base::Type attacherType, eMapMode mmode)
case mmObjectYZ:
return TwoStrings(qApp->translate("Attacher3D", "Object's Y Z X","Attachment3D mode caption"),
qApp->translate("Attacher3D", "X', Y', Z' axes are matched with object's local Y, Z, X, respectively.","Attachment3D mode tooltip"));
case mmParallelPlane:
return TwoStrings(qApp->translate("Attacher3D", "XY parallel to plane","Attachment3D mode caption"),
qApp->translate("Attacher3D", "X' Y' plane is parallel to the plane (object's XY) and passes through the vertex.","Attachment3D mode tooltip"));
case mmFlatFace:
return TwoStrings(qApp->translate("Attacher3D", "XY on plane","Attachment3D mode caption"),
qApp->translate("Attacher3D", "X' Y' plane is aligned to coincide planar face.","Attachment3D mode tooltip"));
@@ -138,6 +141,9 @@ TextSet getUIStrings(Base::Type attacherType, eMapMode mmode)
case mmObjectYZ:
return TwoStrings(qApp->translate("Attacher2D", "Object's YZ","AttachmentPlane mode caption"),
qApp->translate("Attacher2D", "Plane is aligned to YZ local plane of linked object.","AttachmentPlane mode tooltip"));
case mmParallelPlane:
return TwoStrings(qApp->translate("Attacher2D", "XY parallel to plane","AttachmentPlane mode caption"),
qApp->translate("Attacher2D", "X' Y' plane is parallel to the plane (object's XY) and passes through the vertex","AttachmentPlane mode tooltip"));
case mmFlatFace:
return TwoStrings(qApp->translate("Attacher2D", "Plane face","AttachmentPlane mode caption"),
qApp->translate("Attacher2D", "Plane is aligned to coincide planar face.","AttachmentPlane mode tooltip"));

View File

@@ -171,6 +171,8 @@ TEST_F(AttacherTest, TestAllStringModesValid)
"OXZ",
"OYZ",
"OYX",
"ParallelPlane",
};
int index = 0;
for (auto mode : modes) {
@@ -197,6 +199,9 @@ TEST_F(AttacherTest, TestAllModesBoundaries)
_boxes[1]->recomputeFeature();
EXPECT_TRUE(boxesMatch(_boxes[1]->Shape.getBoundingBox(), Base::BoundBox3d(0, 0, 0, 3, 1, 2)));
_boxes[1]->MapMode.setValue(mmParallelPlane);
_boxes[1]->recomputeFeature();
EXPECT_TRUE(boxesMatch(_boxes[1]->Shape.getBoundingBox(), Base::BoundBox3d(0, 0, 0, 3, 1, 2)));
_boxes[1]->MapMode.setValue(mmFlatFace);
_boxes[1]->recomputeFeature();
EXPECT_TRUE(boxesMatch(_boxes[1]->Shape.getBoundingBox(), Base::BoundBox3d(0, 0, 0, 3, 1, 2)));