[TD]fix centerline rotation

This commit is contained in:
wandererfan
2023-09-23 12:16:17 -04:00
committed by WandererFan
parent a51c54e7f0
commit 084b33d3e4
5 changed files with 161 additions and 50 deletions

View File

@@ -31,16 +31,16 @@
#include <TopoDS_Shape.hxx>
#endif
#include <BRepTools.hxx>
#include <Base/Console.h>
#include <Base/Persistence.h>
#include "CenterLine.h"
#include "DrawUtil.h"
#include "DrawViewPart.h"
#include "Geometry.h"
#include "GeometryObject.h"
#include "CenterLinePy.h"
#include "ShapeUtils.h"
using namespace TechDraw;
using DU = DrawUtil;
@@ -274,6 +274,84 @@ TechDraw::BaseGeomPtr CenterLine::scaledGeometry(const TechDraw::DrawViewPart* p
return newGeom;
}
TechDraw::BaseGeomPtr CenterLine::scaledAndRotatedGeometry(TechDraw::DrawViewPart* partFeat)
{
// Base::Console().Message("CL::scaledGeometry() - m_type: %d\n", m_type);
double scale = partFeat->getScale();
double viewAngleDeg = partFeat->Rotation.getValue();
std::pair<Base::Vector3d, Base::Vector3d> ends;
try {
if (m_faces.empty() &&
m_edges.empty() &&
m_verts.empty() ) {
// Base::Console().Message("CL::scaledGeometry - no geometry to scale!\n");
//CenterLine was created by points without a geometry reference,
ends = calcEndPointsNoRef(m_start, m_end, scale, m_extendBy,
m_hShift, m_vShift, m_rotate, viewAngleDeg);
} else if (m_type == CLTYPE::FACE) {
ends = calcEndPoints(partFeat,
m_faces,
m_mode, m_extendBy,
m_hShift, m_vShift, m_rotate);
} else if (m_type == CLTYPE::EDGE) {
ends = calcEndPoints2Lines(partFeat,
m_edges,
m_mode,
m_extendBy,
m_hShift, m_vShift, m_rotate, m_flip2Line);
} else if (m_type == CLTYPE::VERTEX) {
ends = calcEndPoints2Points(partFeat,
m_verts,
m_mode,
m_extendBy,
m_hShift, m_vShift, m_rotate, m_flip2Line);
}
}
catch (...) {
Base::Console().Error("CL::scaledGeometry - failed to calculate endpoints!\n");
return nullptr;
}
// inversion here breaks face cl.
Base::Vector3d p1 = ends.first;
Base::Vector3d p2 = ends.second;
if (p1.IsEqual(p2, 0.00001)) {
Base::Console().Warning("Centerline endpoints are equal. Could not draw.\n");
//what to do here? //return current geom?
return m_geometry;
}
TopoDS_Edge newEdge;
if (getType() == CLTYPE::FACE ) {
gp_Pnt gp1(DU::togp_Pnt(p1));
gp_Pnt gp2(DU::togp_Pnt(p2));
TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp1, gp2);
// Mirror shape in Y and scale
TopoDS_Shape s = ShapeUtils::mirrorShape(e, gp_Pnt(0.0, 0.0, 0.0), scale);
// rotate using OXYZ as the coordinate system
s = ShapeUtils::rotateShape(s, gp_Ax2(), - partFeat->Rotation.getValue());
newEdge = TopoDS::Edge(s);
} else if (getType() == CLTYPE::EDGE ||
getType() == CLTYPE::VERTEX) {
gp_Pnt gp1(DU::togp_Pnt(DU::invertY(p1 * scale)));
gp_Pnt gp2(DU::togp_Pnt(DU::invertY(p2 * scale)));
newEdge = BRepBuilderAPI_MakeEdge(gp1, gp2);
}
TechDraw::BaseGeomPtr newGeom = TechDraw::BaseGeom::baseFactory(newEdge);
if (!newGeom) {
throw Base::RuntimeError("Failed to create center line");
}
newGeom->setClassOfEdge(ecHARD);
newGeom->setHlrVisible( true);
newGeom->setCosmetic(true);
newGeom->source(CENTERLINE);
newGeom->setCosmeticTag(getTagAsString());
return newGeom;
}
std::string CenterLine::toString() const
{
std::stringstream ss;
@@ -417,12 +495,20 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints(const DrawVi
}
}
TopoDS_Shape faceEdgeCompound = DU::vectorToCompound(faceEdgesAll);
if (partFeat->Rotation.getValue() != 0.0) {
// align a copy of the input shape with the cardinal axes so we can use bbox to
// get size measurements
faceEdgeCompound = ShapeUtils::rotateShape(faceEdgeCompound, partFeat->getProjectionCS(), partFeat->Rotation.getValue() * -1.0);
}
if (partFeat->Rotation.getValue() != 0.0) {
// unrotate the input shape to align with the cardinal axes so we can use bbox to
// get size measurements
faceEdgeCompound = ShapeUtils::rotateShape(faceEdgeCompound,
partFeat->getProjectionCS(),
partFeat->Rotation.getValue() * -1.0);
}
// get the center of the unrotated, scaled face
Base::Vector3d faceCenter = ShapeUtils::findCentroidVec(faceEdgeCompound, partFeat->getProjectionCS());
// we need to move the edges to the origin here to get the right limits from the bounding box
faceEdgeCompound = ShapeUtils::moveShape(faceEdgeCompound, faceCenter * -1.0);
// get the bounding box of the centered and unrotated face
BRepBndLib::AddOptimal(faceEdgeCompound, faceBox);
if (faceBox.IsVoid()) {
@@ -435,11 +521,14 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints(const DrawVi
double Xspan = fabs(Xmax - Xmin);
Xspan = (Xspan / 2.0);
double Xmid = Xmin + Xspan;
double Xmid = 0.0;
Xmax = Xmid + Xspan;
Xmin = Xmid - Xspan;
double Yspan = fabs(Ymax - Ymin);
Yspan = (Yspan / 2.0);
double Ymid = Ymin + Yspan;
double Ymid = 0.0;
Ymax = Ymid + Yspan;
Ymin = Ymid - Yspan;
Base::Vector3d p1, p2;
if (mode == CenterLine::VERTICAL) { //vertical
@@ -454,6 +543,12 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints(const DrawVi
p2 = Base::Vector3d(Xmid, Ymin, 0.0);
}
// now move the extents back to the face center. this should give us the scaled,
// unrotated ends of the cl (but in 3d coordinates, which will be handled at the time
// the cl is added to the view)
p1 += faceCenter;
p2 += faceCenter;
Base::Vector3d mid = (p1 + p2) / 2.0;
//extend
@@ -480,14 +575,9 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints(const DrawVi
p2.y = p2.y + vss;
}
// rotate the endpoints so that when the View's Rotation is applied, the
// centerline is aligned correctly
std::pair<Base::Vector3d, Base::Vector3d> result;
result.first = p1 / scale;
result.second = p2 / scale;
Base::Vector3d midpoint = (result.first + result.second) / 2.0;
result = rotatePointsAroundMid(result.first, result.second, midpoint, partFeat->Rotation.getValue() * -1.0);
return result;
}
@@ -511,7 +601,6 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints2Lines(const
}
double scale = partFeat->getScale();
const std::vector<TechDraw::BaseGeomPtr> dbEdges = partFeat->getEdgeGeometry();
std::vector<TechDraw::BaseGeomPtr> edges;
for (auto& en: edgeNames) {
@@ -528,14 +617,15 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints2Lines(const
}
if (edges.size() != 2) {
Base::Console().Message("CL::calcEndPoints2Lines - wrong number of edges: %d!\n", edges.size());
// return result;
throw Base::IndexError("CenterLine wrong number of edges.");
}
Base::Vector3d l1p1 = edges.front()->getStartPoint();
Base::Vector3d l1p2 = edges.front()->getEndPoint();
Base::Vector3d l2p1 = edges.back()->getStartPoint();
Base::Vector3d l2p2 = edges.back()->getEndPoint();
// these points are centered, rotated, scaled and inverted.
// invert the points so the math works correctly
Base::Vector3d l1p1 = DU::invertY(edges.front()->getStartPoint());
Base::Vector3d l1p2 = DU::invertY(edges.front()->getEndPoint());
Base::Vector3d l2p1 = DU::invertY(edges.back()->getStartPoint());
Base::Vector3d l2p2 = DU::invertY(edges.back()->getEndPoint());
// The centerline is drawn using the midpoints of the two lines that connect l1p1-l2p1 and l1p2-l2p2.
// However, we don't know which point should be l1p1 to get a geometrically correct result, see
@@ -568,14 +658,17 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints2Lines(const
}
//orientation
if (mode == CenterLine::VERTICAL && !inhibitVertical) { //Vertical
p1.x = mid.x;
p2.x = mid.x;
} else if (mode == CenterLine::HORIZONTAL && !inhibitHorizontal) { //Horizontal
p1.y = mid.y;
p2.y = mid.y;
} else if (mode == CenterLine::ALIGNED) { //Aligned
// no op
if (partFeat->Rotation.getValue() == 0.0) {
// if the view is rotated, then horizontal and vertical lose their meaning
if (mode == 0 && !inhibitVertical) { //Vertical
p1.x = mid.x;
p2.x = mid.x;
} else if (mode == 1 && !inhibitHorizontal) { //Horizontal
p1.y = mid.y;
p2.y = mid.y;
} else if (mode == 2) { //Aligned
// no op
}
}
//extend
@@ -587,9 +680,7 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints2Lines(const
//rotate
if (!DrawUtil::fpCompare(rotate, 0.0)) {
//rotate p1, p2 about mid
std::pair<Base::Vector3d, Base::Vector3d> ends = rotatePointsAroundMid(p1, p2, mid, rotate);
p1 = ends.first;
p2 = ends.second;
std::tie(p1, p2) = rotatePointsAroundMid(p1, p2, mid, rotate);
}
//shift
@@ -604,13 +695,9 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints2Lines(const
p2.y = p2.y + vss;
}
// rotate the endpoints so that when the View's Rotation is applied, the
// centerline is aligned correctly
// the cl will be scaled when drawn, so unscale now.
result.first = p1 / scale;
result.second = p2 / scale;
Base::Vector3d midpoint = (result.first + result.second) / 2.0;
result = rotatePointsAroundMid(result.first, result.second, midpoint, partFeat->Rotation.getValue() * -1.0);
return result;
}
@@ -647,8 +734,8 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints2Points(const
throw Base::IndexError("CenterLine wrong number of points.");
}
Base::Vector3d v1 = points.front()->point();
Base::Vector3d v2 = points.back()->point();
Base::Vector3d v1 = DU::invertY(points.front()->point());
Base::Vector3d v2 = DU::invertY(points.back()->point());
Base::Vector3d mid = (v1 + v2) / 2.0;
Base::Vector3d dir = v2 - v1;
@@ -667,16 +754,20 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints2Points(const
inhibitVertical = true;
}
if (mode == CenterLine::VERTICAL && !inhibitVertical) {
//orientation
if (partFeat->Rotation.getValue() == 0.0) {
// if the view is rotated, then horizontal and vertical lose their meaning
if (mode == CenterLine::VERTICAL && !inhibitVertical) {
//Vertical
v1.x = mid.x;
v2.x = mid.x;
} else if (mode == CenterLine::HORIZONTAL && !inhibitHorizontal) {
} else if (mode == CenterLine::HORIZONTAL && !inhibitHorizontal) {
//Horizontal
v1.y = mid.y;
v2.y = mid.y;
} else if (mode == CenterLine::ALIGNED) { //Aligned
// no op
} else if (mode == CenterLine::ALIGNED) { //Aligned
// no op
}
}
double length = dir.Length();
@@ -714,8 +805,6 @@ std::pair<Base::Vector3d, Base::Vector3d> CenterLine::calcEndPoints2Points(const
p2.y = p2.y + vss;
}
// in the case of points, we do not need to apply a rotation, since the points will
// rotated already
std::pair<Base::Vector3d, Base::Vector3d> result;
result.first = p1 / scale;
result.second = p2 / scale;

View File

@@ -88,6 +88,7 @@ public:
const int mode = 0,
const bool flip = false);
TechDraw::BaseGeomPtr scaledGeometry(const TechDraw::DrawViewPart* partFeat);
TechDraw::BaseGeomPtr scaledAndRotatedGeometry(TechDraw::DrawViewPart* partFeat);
static std::pair<Base::Vector3d, Base::Vector3d> rotatePointsAroundMid(
const Base::Vector3d& p1,
@@ -139,6 +140,8 @@ public:
double getExtend() const;
void setFlip(const bool f);
bool getFlip() const;
void setType(const int type) { m_type = type; };
int getType() const { return m_type; }
Base::Vector3d m_start;
Base::Vector3d m_end;

View File

@@ -341,7 +341,7 @@ TechDraw::CosmeticEdge* CosmeticExtension::getCosmeticEdge(const std::string& ta
}
// None found
Base::Console().Message("CEx::getCosmeticEdge - CE for tag: %s not found.\n", tagString.c_str());
// Base::Console().Message("CEx::getCosmeticEdge - CE for tag: %s not found.\n", tagString.c_str());
return nullptr;
}
@@ -416,10 +416,11 @@ int CosmeticExtension::add1CLToGE(const std::string& tag)
// Base::Console().Message("CEx::add1CLToGE(%s) 2\n", tag.c_str());
TechDraw::CenterLine* cl = getCenterLine(tag);
if (!cl) {
Base::Console().Message("CEx::add1CLToGE 2 - cl %s not found\n", tag.c_str());
// Base::Console().Message("CEx::add1CLToGE 2 - cl %s not found\n", tag.c_str());
return -1;
}
TechDraw::BaseGeomPtr scaledGeom = cl->scaledGeometry(getOwner());
TechDraw::BaseGeomPtr scaledGeom = cl->scaledAndRotatedGeometry(getOwner());
// TechDraw::BaseGeomPtr scaledGeom = cl->scaledGeometry(getOwner());
int iGE = getOwner()->getGeometryObject()->addCenterLine(scaledGeom, tag);
return iGE;
@@ -446,7 +447,8 @@ void CosmeticExtension::addCenterLinesToGeom()
// Base::Console().Message("CE::addCenterLinesToGeom()\n");
const std::vector<TechDraw::CenterLine*> lines = CenterLines.getValues();
for (auto& cl : lines) {
TechDraw::BaseGeomPtr scaledGeom = cl->scaledGeometry(getOwner());
// TechDraw::BaseGeomPtr scaledGeom = cl->scaledGeometry(getOwner());
TechDraw::BaseGeomPtr scaledGeom = cl->scaledAndRotatedGeometry(getOwner());
if (!scaledGeom) {
Base::Console().Error("CE::addCenterLinesToGeom - scaledGeometry is null\n");
continue;
@@ -491,7 +493,6 @@ std::string CosmeticExtension::addCenterLine(TechDraw::BaseGeomPtr bg)
return cl->getTagAsString();
}
//get CL by unique id
TechDraw::CenterLine* CosmeticExtension::getCenterLine(const std::string& tagString) const
{

View File

@@ -353,3 +353,17 @@ TopoDS_Shape ShapeUtils::centerShapeXY(const TopoDS_Shape& inShape, const gp_Ax2
Base::Vector3d centroid = DrawUtil::toVector3d(inputCenter);
return ShapeUtils::moveShape(inShape, centroid * -1.0);
}
std::pair<Base::Vector3d, Base::Vector3d> ShapeUtils::getEdgeEnds(TopoDS_Edge edge)
{
std::pair<Base::Vector3d, Base::Vector3d> result;
TopoDS_Vertex tvFirst, tvLast;
TopExp::Vertices(edge, tvFirst, tvLast);
gp_Pnt gpFirst = BRep_Tool::Pnt(tvFirst);
gp_Pnt gpLast = BRep_Tool::Pnt(tvLast);
result.first = DU::toVector3d(gpFirst);
result.second = DU::toVector3d(gpLast);
return result;
}

View File

@@ -30,6 +30,7 @@
#include <vector>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Edge.hxx>
#include <gp_Ax2.hxx>
#include <gp_Pnt.hxx>
@@ -104,6 +105,9 @@ public:
static TopoDS_Shape projectSimpleShape(const TopoDS_Shape& shape, const gp_Ax2& CS);
static TopoDS_Shape simpleProjection(const TopoDS_Shape& shape, const gp_Ax2& projCS);
static TopoDS_Shape projectFace(const TopoDS_Shape& face, const gp_Ax2& CS);
static std::pair<Base::Vector3d, Base::Vector3d> getEdgeEnds(TopoDS_Edge edge);
};
}