[TD] Include Intersection method into DrawUtil class
This commit is contained in:
@@ -543,6 +543,171 @@ bool BaseGeom::validateEdge(TopoDS_Edge edge)
|
||||
return !DrawUtil::isCrazy(edge);
|
||||
}
|
||||
|
||||
std::vector<Base::Vector3d> BaseGeom::intersection(TechDraw::BaseGeomPtr geom2)
|
||||
{
|
||||
// find intersection vertex(es) between two edges
|
||||
// permitted are: line, circle or arc of circle
|
||||
// call: interPoints = line1.intersection(line2);
|
||||
# define unknown 0
|
||||
# define isGeneric 1
|
||||
# define isArcOrCircle 2
|
||||
// we check the type of the two objects
|
||||
int edge1(unknown), edge2(unknown);
|
||||
if (this->geomType == TechDraw::CIRCLE ||
|
||||
this->geomType == TechDraw::ARCOFCIRCLE)
|
||||
edge1 = isArcOrCircle;
|
||||
else if (this->geomType == TechDraw::GENERIC)
|
||||
edge1 = isGeneric;
|
||||
if (geom2->geomType == TechDraw::CIRCLE ||
|
||||
geom2->geomType == TechDraw::ARCOFCIRCLE)
|
||||
edge2 = isArcOrCircle;
|
||||
else if (geom2->geomType == TechDraw::GENERIC)
|
||||
edge2 = isGeneric;
|
||||
// we calculate the intersections
|
||||
std::vector<Base::Vector3d> interPoints;
|
||||
if (edge1 == isGeneric && edge2 == isGeneric)
|
||||
intersectionLL(shared_from_this(), geom2, interPoints);
|
||||
else if (edge1 == isArcOrCircle && edge2 == isGeneric)
|
||||
intersectionCL(shared_from_this(), geom2, interPoints);
|
||||
else if (edge1 == isGeneric && edge2 == isArcOrCircle)
|
||||
intersectionCL(geom2, shared_from_this(), interPoints);
|
||||
else if (edge1 == isArcOrCircle && edge2 == isArcOrCircle)
|
||||
intersectionCC(shared_from_this(), geom2, interPoints);
|
||||
return interPoints;
|
||||
}
|
||||
|
||||
void BaseGeom::intersectionLL(TechDraw::BaseGeomPtr geom1,
|
||||
TechDraw::BaseGeomPtr geom2,
|
||||
std::vector<Base::Vector3d>& interPoints)
|
||||
{
|
||||
// find intersection vertex of two lines
|
||||
// Taken from: <http://de.wikipedia.org/wiki/Schnittpunkt>
|
||||
TechDraw::GenericPtr gen1 = std::static_pointer_cast<TechDraw::Generic>(geom1);
|
||||
TechDraw::GenericPtr gen2 = std::static_pointer_cast<TechDraw::Generic>(geom2);
|
||||
// we calculate vectors to start points and direction verctors
|
||||
Base::Vector3d startPnt1 = gen1->points.at(0);
|
||||
Base::Vector3d endPnt1 = gen1->points.at(1);
|
||||
Base::Vector3d startPnt2 = gen2->points.at(0);
|
||||
Base::Vector3d endPnt2 = gen2->points.at(1);
|
||||
Base::Vector3d dir1 = endPnt1 - startPnt1;
|
||||
Base::Vector3d dir2 = endPnt2 - startPnt2;
|
||||
// we create equations a*x+b*y+c=0 for both lines
|
||||
float a1 = -dir1.y;
|
||||
float b1 = dir1.x;
|
||||
float c1 = -startPnt1.x * dir1.y + startPnt1.y * dir1.x;
|
||||
float a2 = -dir2.y;
|
||||
float b2 = dir2.x;
|
||||
float c2 = -startPnt2.x * dir2.y + startPnt2.y * dir2.x;
|
||||
float denom = a1 * b2 - a2 * b1;
|
||||
if (abs(denom) >= 0.01)
|
||||
// lines not (nearly) parallel, we calculate intersections
|
||||
{
|
||||
float xIntersect = (c1 * b2 - c2 * b1) / denom;
|
||||
float yIntersect = (a1 * c2 - a2 * c1) / denom;
|
||||
yIntersect = -yIntersect;
|
||||
Base::Vector3d interPoint(xIntersect, yIntersect, 0.0);
|
||||
interPoints.push_back(interPoint);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseGeom::intersectionCL(TechDraw::BaseGeomPtr geom1,
|
||||
TechDraw::BaseGeomPtr geom2,
|
||||
std::vector<Base::Vector3d>& interPoints)
|
||||
{
|
||||
// find intersection vertex(es) between one circle and one line
|
||||
// Taken from: <http://de.wikipedia.org/wiki/Schnittpunkt>
|
||||
TechDraw::CirclePtr gen1 = std::static_pointer_cast<TechDraw::Circle>(geom1);
|
||||
TechDraw::GenericPtr gen2 = std::static_pointer_cast<TechDraw::Generic>(geom2);
|
||||
// we calculate vectors to circle center, start point and direction vector
|
||||
Base::Vector3d cirleCenter = gen1->center;
|
||||
Base::Vector3d startPnt = gen2->points.at(0);
|
||||
Base::Vector3d endPnt = gen2->points.at(1);
|
||||
Base::Vector3d dir = endPnt - startPnt;
|
||||
// we create equations of the circle: (x-x0)^2+(y-y0)^2=r^2
|
||||
// and the line: a*x+b*y+c=0
|
||||
float r0 = gen1->radius;
|
||||
float x0 = cirleCenter.x;
|
||||
float y0 = cirleCenter.y;
|
||||
float a = -dir.y;
|
||||
float b = dir.x;
|
||||
float c = -startPnt.x * dir.y + startPnt.y * dir.x;
|
||||
// we shift line and circle so that the circle center is in the origin
|
||||
// and calculate constant d of new line equation
|
||||
float d = c - a * x0 - b * y0;
|
||||
float ab = a * a + b * b;
|
||||
float rootArg = r0 * r0 * ab - d * d;
|
||||
if (rootArg > 0)
|
||||
// line and circle have common points
|
||||
{
|
||||
if (rootArg < 0.01)
|
||||
// line is the tangent line, one intersection point
|
||||
{
|
||||
float x1 = x0 + a * d / ab;
|
||||
float y1 = -y0 + b * d / ab;
|
||||
Base::Vector3d interPoint1(x1, y1, 0.0);
|
||||
interPoints.push_back(interPoint1);
|
||||
}
|
||||
else
|
||||
// line is crossing the circle, two intersection points
|
||||
{
|
||||
float root = sqrt(rootArg);
|
||||
float x1 = x0 + (a * d + b * root) / ab;
|
||||
float y1 = -y0 - (b * d - a * root) / ab;
|
||||
float x2 = x0 + (a * d - b * root) / ab;
|
||||
float y2 = -y0 - (b * d + a * root) / ab;
|
||||
Base::Vector3d interPoint1(x1, y1, 0.0);
|
||||
interPoints.push_back(interPoint1);
|
||||
Base::Vector3d interPoint2(x2, y2, 0.0);
|
||||
interPoints.push_back(interPoint2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BaseGeom::intersectionCC(TechDraw::BaseGeomPtr geom1,
|
||||
TechDraw::BaseGeomPtr geom2,
|
||||
std::vector<Base::Vector3d>& interPoints)
|
||||
{
|
||||
// find intersection vertex(es) between two circles
|
||||
// Taken from: <http://de.wikipedia.org/wiki/Schnittpunkt>
|
||||
TechDraw::CirclePtr gen1 = std::static_pointer_cast<TechDraw::Circle>(geom1);
|
||||
TechDraw::CirclePtr gen2 = std::static_pointer_cast<TechDraw::Circle>(geom2);
|
||||
Base::Vector3d Center1 = gen1->center;
|
||||
Base::Vector3d Center2 = gen2->center;
|
||||
float r1 = gen1->radius;
|
||||
float r2 = gen2->radius;
|
||||
// we calculate the distance d12 of the centers, and the
|
||||
// two orthonormal vectors m and n
|
||||
float d12 = (Center2 - Center1).Length();
|
||||
Base::Vector3d m = (Center2 - Center1).Normalize();
|
||||
Base::Vector3d n(-m.y, m.x, 0.0);
|
||||
// we calculate d0, the distance from center1 to the tie line
|
||||
// and rootArg, the square of the distance of the intersection points
|
||||
float d0 = (r1 * r1 - r2 * r2 + d12 * d12) / (2 * d12);
|
||||
float rootArg = r1 * r1 - d0 * d0;
|
||||
if (rootArg > 0)
|
||||
// the circles have intersection points
|
||||
{
|
||||
if (rootArg < 0.1)
|
||||
// the circles touch, one intersection point
|
||||
{
|
||||
Base::Vector3d interPoint1 = -Center1 + m * d0;
|
||||
interPoint1.y = -interPoint1.y;
|
||||
interPoints.push_back(interPoint1);
|
||||
}
|
||||
else
|
||||
// the circles have two intersection points
|
||||
{
|
||||
float e0 = sqrt(rootArg);
|
||||
Base::Vector3d interPoint1 = Center1 + m * d0 + n * e0;
|
||||
interPoint1.y = -interPoint1.y;
|
||||
interPoints.push_back(interPoint1);
|
||||
Base::Vector3d interPoint2 = Center1 + m * d0 - n * e0;
|
||||
interPoint2.y = -interPoint2.y;
|
||||
interPoints.push_back(interPoint2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ellipse::Ellipse(const TopoDS_Edge &e)
|
||||
{
|
||||
geomType = ELLIPSE;
|
||||
|
||||
@@ -93,7 +93,7 @@ using BSplinePtr = std::shared_ptr<BSpline>;
|
||||
class Generic;
|
||||
using GenericPtr = std::shared_ptr<Generic>;
|
||||
|
||||
class TechDrawExport BaseGeom
|
||||
class TechDrawExport BaseGeom : public std::enable_shared_from_this<BaseGeom>
|
||||
{
|
||||
public:
|
||||
BaseGeom();
|
||||
@@ -132,11 +132,23 @@ class TechDrawExport BaseGeom
|
||||
bool closed(void);
|
||||
BaseGeomPtr copy();
|
||||
std::string dump();
|
||||
std::vector<Base::Vector3d> intersection(TechDraw::BaseGeomPtr geom2);
|
||||
|
||||
//Uniqueness
|
||||
boost::uuids::uuid getTag() const;
|
||||
virtual std::string getTagAsString(void) const;
|
||||
|
||||
private:
|
||||
void intersectionLL(TechDraw::BaseGeomPtr geom1,
|
||||
TechDraw::BaseGeomPtr geom2,
|
||||
std::vector<Base::Vector3d>& interPoints);
|
||||
void intersectionCL(TechDraw::BaseGeomPtr geom1,
|
||||
TechDraw::BaseGeomPtr geom2,
|
||||
std::vector<Base::Vector3d>& interPoints);
|
||||
void intersectionCC(TechDraw::BaseGeomPtr geom1,
|
||||
TechDraw::BaseGeomPtr geom2,
|
||||
std::vector<Base::Vector3d>& interPoints);
|
||||
|
||||
protected:
|
||||
int m_source; //0 - geom, 1 - cosmetic edge, 2 - centerline
|
||||
int m_sourceIndex;
|
||||
|
||||
@@ -83,10 +83,6 @@ namespace TechDrawGui {
|
||||
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge);
|
||||
void _setLineAttributes(TechDraw::CenterLine* cosEdge);
|
||||
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge, int style, float weight, App::Color color);
|
||||
void _intersection(TechDraw::BaseGeomPtr geom1, TechDraw::BaseGeomPtr geom2, std::vector<Base::Vector3d>& interPoints);
|
||||
void _intersectionLL(TechDraw::BaseGeomPtr geom1, TechDraw::BaseGeomPtr geom2, std::vector<Base::Vector3d>& interPoints);
|
||||
void _intersectionCL(TechDraw::BaseGeomPtr geom1, TechDraw::BaseGeomPtr geom2, std::vector<Base::Vector3d>& interPoints);
|
||||
void _intersectionCC(TechDraw::BaseGeomPtr geom1, TechDraw::BaseGeomPtr geom2, std::vector<Base::Vector3d>& interPoints);
|
||||
float _getAngle(Base::Vector3d center, Base::Vector3d point);
|
||||
std::vector<Base::Vector3d> _getVertexPoints(std::vector<std::string> SubNames, TechDraw::DrawViewPart* objFeat);
|
||||
bool _checkSel(Gui::Command* cmd,
|
||||
@@ -828,7 +824,7 @@ void CmdTechDrawExtensionVertexAtIntersection::activated(int iMsg)
|
||||
TechDraw::BaseGeomPtr geom1 = objFeat->getGeomByIndex(GeoId1);
|
||||
int GeoId2 = TechDraw::DrawUtil::getIndexFromName(SubNames[1]);
|
||||
TechDraw::BaseGeomPtr geom2 = objFeat->getGeomByIndex(GeoId2);
|
||||
_intersection(geom1, geom2, interPoints);
|
||||
interPoints = geom1->intersection(geom2);
|
||||
if (!interPoints.empty()) {
|
||||
double scale = objFeat->getScale();
|
||||
std::string id1 = objFeat->addCosmeticVertex(interPoints[0] / scale);
|
||||
@@ -1852,130 +1848,6 @@ namespace TechDrawGui {
|
||||
return angle;
|
||||
}
|
||||
|
||||
void _intersection(TechDraw::BaseGeomPtr geom1, TechDraw::BaseGeomPtr geom2, std::vector<Base::Vector3d>& interPoints) {
|
||||
// find intersection vertex(es) between two edges
|
||||
#define unknown 0
|
||||
#define isLine 1
|
||||
#define isCircle 2
|
||||
int edge1(unknown), edge2(unknown);
|
||||
if (geom1->geomType == TechDraw::CIRCLE ||
|
||||
geom1->geomType == TechDraw::ARCOFCIRCLE)
|
||||
edge1 = isCircle;
|
||||
else if (geom1->geomType == TechDraw::GENERIC)
|
||||
edge1 = isLine;
|
||||
if (geom2->geomType == TechDraw::CIRCLE ||
|
||||
geom2->geomType == TechDraw::ARCOFCIRCLE)
|
||||
edge2 = isCircle;
|
||||
else if (geom2->geomType == TechDraw::GENERIC)
|
||||
edge2 = isLine;
|
||||
if (edge1 == isLine && edge2 == isLine)
|
||||
_intersectionLL(geom1, geom2, interPoints);
|
||||
else if (edge1 == isCircle && edge2 == isLine)
|
||||
_intersectionCL(geom1, geom2, interPoints);
|
||||
else if (edge1 == isLine && edge2 == isCircle)
|
||||
_intersectionCL(geom2, geom1, interPoints);
|
||||
else if (edge1 == isCircle && edge2 == isCircle)
|
||||
_intersectionCC(geom2, geom1, interPoints);
|
||||
}
|
||||
|
||||
void _intersectionLL(TechDraw::BaseGeomPtr geom1, TechDraw::BaseGeomPtr geom2, std::vector<Base::Vector3d>& interPoints) {
|
||||
// find intersection vertex of two lines
|
||||
// Taken from: <http://de.wikipedia.org/wiki/Schnittpunkt>
|
||||
TechDraw::GenericPtr gen1 = std::static_pointer_cast<TechDraw::Generic>(geom1);
|
||||
TechDraw::GenericPtr gen2 = std::static_pointer_cast<TechDraw::Generic>(geom2);
|
||||
Base::Vector3d startPnt1 = gen1->points.at(0);
|
||||
Base::Vector3d endPnt1 = gen1->points.at(1);
|
||||
Base::Vector3d startPnt2 = gen2->points.at(0);
|
||||
Base::Vector3d endPnt2 = gen2->points.at(1);
|
||||
Base::Vector3d dir1 = endPnt1 - startPnt1;
|
||||
Base::Vector3d dir2 = endPnt2 - startPnt2;
|
||||
float a1 = -dir1.y;
|
||||
float b1 = dir1.x;
|
||||
float c1 = -startPnt1.x * dir1.y + startPnt1.y * dir1.x;
|
||||
float a2 = -dir2.y;
|
||||
float b2 = dir2.x;
|
||||
float c2 = -startPnt2.x * dir2.y + startPnt2.y * dir2.x;
|
||||
float denom = a1 * b2 - a2 * b1;
|
||||
if (abs(denom) >= 0.01) {
|
||||
float xIntersect = (c1 * b2 - c2 * b1) / denom;
|
||||
float yIntersect = (a1 * c2 - a2 * c1) / denom;
|
||||
yIntersect = -yIntersect;
|
||||
Base::Vector3d interPoint(xIntersect, yIntersect, 0.0);
|
||||
interPoints.push_back(interPoint);
|
||||
}
|
||||
}
|
||||
|
||||
void _intersectionCL(TechDraw::BaseGeomPtr geom1, TechDraw::BaseGeomPtr geom2, std::vector<Base::Vector3d>& interPoints) {
|
||||
// find intersection vertex(es) between one circle and one line
|
||||
// Taken from: <http://de.wikipedia.org/wiki/Schnittpunkt>
|
||||
TechDraw::CirclePtr gen1 = std::static_pointer_cast<TechDraw::Circle>(geom1);
|
||||
TechDraw::GenericPtr gen2 = std::static_pointer_cast<TechDraw::Generic>(geom2);
|
||||
Base::Vector3d cirleCenter = gen1->center;
|
||||
Base::Vector3d startPnt = gen2->points.at(0);
|
||||
Base::Vector3d endPnt = gen2->points.at(1);
|
||||
Base::Vector3d dir = endPnt - startPnt;
|
||||
float r0 = gen1->radius;
|
||||
float x0 = cirleCenter.x;
|
||||
float y0 = cirleCenter.y;
|
||||
float a = -dir.y;
|
||||
float b = dir.x;
|
||||
float c = -startPnt.x * dir.y + startPnt.y * dir.x;
|
||||
float d = c - a * x0 - b * y0;
|
||||
float ab = a * a + b * b;
|
||||
float rootArg = r0 * r0 * ab - d * d;
|
||||
if (rootArg > 0) {
|
||||
if (rootArg < 0.01) {
|
||||
float x1 = x0 + a * d / ab;
|
||||
float y1 = -y0 + b * d / ab;
|
||||
Base::Vector3d interPoint1(x1, y1, 0.0);
|
||||
interPoints.push_back(interPoint1);
|
||||
}
|
||||
else {
|
||||
float root = sqrt(rootArg);
|
||||
float x1 = x0 + (a * d + b * root) / ab;
|
||||
float y1 = -y0 - (b * d - a * root) / ab;
|
||||
float x2 = x0 + (a * d - b * root) / ab;
|
||||
float y2 = -y0 - (b * d + a * root) / ab;
|
||||
Base::Vector3d interPoint1(x1, y1, 0.0);
|
||||
interPoints.push_back(interPoint1);
|
||||
Base::Vector3d interPoint2(x2, y2, 0.0);
|
||||
interPoints.push_back(interPoint2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _intersectionCC(TechDraw::BaseGeomPtr geom1, TechDraw::BaseGeomPtr geom2, std::vector<Base::Vector3d>& interPoints) {
|
||||
// find intersection vertex(es) between two circles
|
||||
// Taken from: <http://de.wikipedia.org/wiki/Schnittpunkt>
|
||||
TechDraw::CirclePtr gen1 = std::static_pointer_cast<TechDraw::Circle>(geom1);
|
||||
TechDraw::CirclePtr gen2 = std::static_pointer_cast<TechDraw::Circle>(geom2);
|
||||
Base::Vector3d Center1 = gen1->center;
|
||||
Base::Vector3d Center2 = gen2->center;
|
||||
float r1 = gen1->radius;
|
||||
float r2 = gen2->radius;
|
||||
float d12 = (Center2 - Center1).Length();
|
||||
Base::Vector3d m = (Center2 - Center1).Normalize();
|
||||
Base::Vector3d n(-m.y, m.x, 0.0);
|
||||
float d0 = (r1 * r1 - r2 * r2 + d12 * d12) / (2 * d12);
|
||||
float rootArg = r1 * r1 - d0 * d0;
|
||||
if (rootArg > 0) {
|
||||
if (rootArg < 0.1) {
|
||||
Base::Vector3d interPoint1 = -Center1 + m * d0;
|
||||
interPoint1.y = -interPoint1.y;
|
||||
interPoints.push_back(interPoint1);
|
||||
}
|
||||
else {
|
||||
float e0 = sqrt(rootArg);
|
||||
Base::Vector3d interPoint1 = Center1 + m * d0 + n * e0;
|
||||
interPoint1.y = -interPoint1.y;
|
||||
interPoints.push_back(interPoint1);
|
||||
Base::Vector3d interPoint2 = Center1 + m * d0 - n * e0;
|
||||
interPoint2.y = -interPoint2.y;
|
||||
interPoints.push_back(interPoint2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Base::Vector3d _circleCenter(Base::Vector3d p1, Base::Vector3d p2, Base::Vector3d p3) {
|
||||
Base::Vector2d v1(p1.x, p1.y);
|
||||
Base::Vector2d v2(p2.x, p2.y);
|
||||
@@ -2100,4 +1972,4 @@ void CreateTechDrawCommandsExtensions(void)
|
||||
rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadHoleBottom());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadBoltBottom());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawExtensionAreaAnnotation());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user