X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fbase%2Frs_information.cpp;fp=src%2Fbase%2Frs_information.cpp;h=54a31809be2e6c9803b43e694a2fd6cef0864050;hb=d86611a87f46873819dfae63f1112b248ba9aca1;hp=c836a2fa7e3f8f3b5fb3a44fdd7fbe4947305181;hpb=a5a416c0a1276401a71b2c0e482af867f4583985;p=architektonas diff --git a/src/base/rs_information.cpp b/src/base/rs_information.cpp index c836a2f..54a3180 100644 --- a/src/base/rs_information.cpp +++ b/src/base/rs_information.cpp @@ -17,6 +17,7 @@ #include "rs_information.h" #include "rs_constructionline.h" +#include "rs_debug.h" /** * Default constructor. @@ -36,33 +37,36 @@ RS_Information::RS_Information(RS_EntityContainer& container) */ bool RS_Information::isDimension(RS2::EntityType type) { - if (type==RS2::EntityDimAligned || - type==RS2::EntityDimLinear || - type==RS2::EntityDimRadial || - type==RS2::EntityDimDiametric || - type==RS2::EntityDimAngular) { - return true; - } else { - return false; - } + if (type == RS2::EntityDimAligned || type == RS2::EntityDimLinear + || type == RS2::EntityDimRadial || type == RS2::EntityDimDiametric + || type == RS2::EntityDimAngular) + { + return true; + } + else + { + return false; + } } - - /** * @retval true the entity can be trimmed. * i.e. it is in a graphic or in a polyline. */ -bool RS_Information::isTrimmable(RS_Entity* e) { - if (e!=NULL) { - if (e->getParent()!=NULL) { - if (e->getParent()->rtti()==RS2::EntityPolyline) { +bool RS_Information::isTrimmable(RS_Entity * e) +{ + if (e) + { + if (e->getParent()) + { + if (e->getParent()->rtti() == RS2::EntityPolyline) + { return true; } - else if (e->getParent()->rtti()==RS2::EntityContainer || - e->getParent()->rtti()==RS2::EntityGraphic || - e->getParent()->rtti()==RS2::EntityBlock) { - + else if (e->getParent()->rtti() == RS2::EntityContainer + || e->getParent()->rtti() == RS2::EntityGraphic + || e->getParent()->rtti() == RS2::EntityBlock) + { // normal entity: return true; } @@ -72,54 +76,58 @@ bool RS_Information::isTrimmable(RS_Entity* e) { return false; } - /** * @retval true the two entities can be trimmed to each other; * i.e. they are in a graphic or in the same polyline. */ -bool RS_Information::isTrimmable(RS_Entity* e1, RS_Entity* e2) { - if (e1!=NULL && e2!=NULL) { - if (e1->getParent()!=NULL && e2->getParent()!=NULL) { - if (e1->getParent()->rtti()==RS2::EntityPolyline && - e2->getParent()->rtti()==RS2::EntityPolyline && - e1->getParent()==e2->getParent()) { - +bool RS_Information::isTrimmable(RS_Entity * e1, RS_Entity * e2) +{ + if (e1 && e2) + { + if (e1->getParent() && e2->getParent()) + { + if (e1->getParent()->rtti() == RS2::EntityPolyline + && e2->getParent()->rtti() == RS2::EntityPolyline + && e1->getParent()==e2->getParent()) + { // in the same polyline - RS_EntityContainer* pl = e1->getParent(); + RS_EntityContainer * pl = e1->getParent(); int idx1 = pl->findEntity(e1); int idx2 = pl->findEntity(e2); - RS_DEBUG->print("RS_Information::isTrimmable: " - "idx1: %d, idx2: %d", idx1, idx2); - if (abs(idx1-idx2)==1 || abs(idx1-idx2)==pl->count()-1) { + RS_DEBUG->print("RS_Information::isTrimmable: idx1: %d, idx2: %d", idx1, idx2); + + if (abs(idx1 - idx2) == 1 || abs(idx1 - idx2) == pl->count() - 1) + { // directly following entities return true; } - else { + else + { // not directly following entities return false; } } - else if ((e1->getParent()->rtti()==RS2::EntityContainer || - e1->getParent()->rtti()==RS2::EntityGraphic || - e1->getParent()->rtti()==RS2::EntityBlock) && - (e2->getParent()->rtti()==RS2::EntityContainer || - e2->getParent()->rtti()==RS2::EntityGraphic || - e2->getParent()->rtti()==RS2::EntityBlock)) { - + else if ((e1->getParent()->rtti() == RS2::EntityContainer + || e1->getParent()->rtti() == RS2::EntityGraphic + || e1->getParent()->rtti() == RS2::EntityBlock) + && (e2->getParent()->rtti() == RS2::EntityContainer + || e2->getParent()->rtti() == RS2::EntityGraphic + || e2->getParent()->rtti() == RS2::EntityBlock)) + { // normal entities: return true; } } - else { + else + { // independent entities with the same parent: - return (e1->getParent()==e2->getParent()); + return (e1->getParent() == e2->getParent()); } } return false; } - /** * Gets the nearest end point to the given coordinate. * @@ -129,12 +137,11 @@ bool RS_Information::isTrimmable(RS_Entity* e1, RS_Entity* e2) { * if there are no elements at all in this graphics * container. */ -Vector RS_Information::getNearestEndpoint(const Vector& coord, - double* dist) const { - return container->getNearestEndpoint(coord, dist); +Vector RS_Information::getNearestEndpoint(const Vector & coord, double * dist) const +{ + return container->getNearestEndpoint(coord, dist); } - /** * Gets the nearest point to the given coordinate which is on an entity. * @@ -148,15 +155,12 @@ Vector RS_Information::getNearestEndpoint(const Vector& coord, * if there are no elements at all in this graphics * container. */ -Vector RS_Information::getNearestPointOnEntity(const Vector& coord, - bool onEntity, - double* dist, - RS_Entity** entity) const { - - return container->getNearestPointOnEntity(coord, onEntity, dist, entity); +Vector RS_Information::getNearestPointOnEntity(const Vector & coord, + bool onEntity, double * dist, RS_Entity ** entity) const +{ + return container->getNearestPointOnEntity(coord, onEntity, dist, entity); } - /** * Gets the nearest entity to the given coordinate. * @@ -168,15 +172,12 @@ Vector RS_Information::getNearestPointOnEntity(const Vector& coord, * @return the entity found or NULL if there are no elements * at all in this graphics container. */ -RS_Entity* RS_Information::getNearestEntity(const Vector& coord, - double* dist, - RS2::ResolveLevel level) const { - - return container->getNearestEntity(coord, dist, level); +RS_Entity * RS_Information::getNearestEntity(const Vector & coord, + double * dist, RS2::ResolveLevel level) const +{ + return container->getNearestEntity(coord, dist, level); } - - /** * Calculates the intersection point(s) between two entities. * @@ -189,478 +190,456 @@ RS_Entity* RS_Information::getNearestEntity(const Vector& coord, * @return All intersections of the two entities. The tangent flag in * VectorSolutions is set if one intersection is a tangent point. */ -VectorSolutions RS_Information::getIntersection(RS_Entity* e1, - RS_Entity* e2, bool onEntities) { - - VectorSolutions ret; +VectorSolutions RS_Information::getIntersection(RS_Entity * e1, + RS_Entity * e2, bool onEntities) +{ + VectorSolutions ret; double tol = 1.0e-4; - if (e1==NULL || e2==NULL) { - return ret; - } - - // unsupported entities / entity combinations: - if ((e1->rtti()==RS2::EntityEllipse && e2->rtti()==RS2::EntityEllipse) || - e1->rtti()==RS2::EntityText || e2->rtti()==RS2::EntityText || - isDimension(e1->rtti()) || isDimension(e2->rtti())) { - - return ret; - } - - // (only) one entity is an ellipse: - if (e1->rtti()==RS2::EntityEllipse || e2->rtti()==RS2::EntityEllipse) { - if (e2->rtti()==RS2::EntityEllipse) { - RS_Entity* tmp = e1; - e1 = e2; - e2 = tmp; - } - if (e2->rtti()==RS2::EntityLine) { - RS_Ellipse* ellipse = (RS_Ellipse*)e1; - ret = getIntersectionLineEllipse((RS_Line*)e2, ellipse); - tol = 1.0e-1; - } + if (!e1 || !e2) + return ret; + // unsupported entities / entity combinations: + if ((e1->rtti() == RS2::EntityEllipse && e2->rtti() == RS2::EntityEllipse) + || e1->rtti() == RS2::EntityText || e2->rtti() == RS2::EntityText + || isDimension(e1->rtti()) || isDimension(e2->rtti())) + { + return ret; + } + + // (only) one entity is an ellipse: + if (e1->rtti() == RS2::EntityEllipse || e2->rtti() == RS2::EntityEllipse) + { + if (e2->rtti() == RS2::EntityEllipse) + { + RS_Entity * tmp = e1; + e1 = e2; + e2 = tmp; + } + + if (e2->rtti() == RS2::EntityLine) + { + RS_Ellipse * ellipse = (RS_Ellipse *)e1; + ret = getIntersectionLineEllipse((RS_Line *)e2, ellipse); + tol = 1.0e-1; + } // ellipse / arc, ellipse / ellipse: not supported: - else { - return ret; - } - } else { + else + { + return ret; + } + } + else + { + RS_Entity * te1 = e1; + RS_Entity * te2 = e2; + + // entity copies - so we only have to deal with lines and arcs + RS_Line l1(NULL, RS_LineData(Vector(0.0, 0.0), Vector(0.0, 0.0))); + RS_Line l2(NULL, RS_LineData(Vector(0.0, 0.0), Vector(0.0, 0.0))); + + RS_Arc a1(NULL, RS_ArcData(Vector(0.0, 0.0), 1.0, 0.0, 2 * M_PI, false)); + RS_Arc a2(NULL, RS_ArcData(Vector(0.0, 0.0), 1.0, 0.0, 2 * M_PI, false)); + + // convert construction lines to lines: + if (e1->rtti() == RS2::EntityConstructionLine) + { + RS_ConstructionLine * cl = (RS_ConstructionLine *)e1; + l1.setStartpoint(cl->getPoint1()); + l1.setEndpoint(cl->getPoint2()); + te1 = &l1; + } - RS_Entity* te1 = e1; - RS_Entity* te2 = e2; + if (e2->rtti() == RS2::EntityConstructionLine) + { + RS_ConstructionLine * cl = (RS_ConstructionLine *)e2; + l2.setStartpoint(cl->getPoint1()); + l2.setEndpoint(cl->getPoint2()); + te2 = &l2; + } - // entity copies - so we only have to deal with lines and arcs - RS_Line l1(NULL, - RS_LineData(Vector(0.0, 0.0), Vector(0.0,0.0))); - RS_Line l2(NULL, - RS_LineData(Vector(0.0, 0.0), Vector(0.0,0.0))); + // convert circles to arcs: + if (e1->rtti() == RS2::EntityCircle) + { + RS_Circle * c = (RS_Circle *)e1; + RS_ArcData data(c->getCenter(), c->getRadius(), 0.0, 2 * M_PI, false); + a1.setData(data); + te1 = &a1; + } - RS_Arc a1(NULL, - RS_ArcData(Vector(0.0,0.0), 1.0, 0.0, 2*M_PI, false)); - RS_Arc a2(NULL, - RS_ArcData(Vector(0.0,0.0), 1.0, 0.0, 2*M_PI, false)); + if (e2->rtti() == RS2::EntityCircle) + { + RS_Circle * c = (RS_Circle *)e2; + RS_ArcData data(c->getCenter(), c->getRadius(), 0.0, 2 * M_PI, false); + a2.setData(data); + te2 = &a2; + } - // convert construction lines to lines: - if (e1->rtti()==RS2::EntityConstructionLine) { - RS_ConstructionLine* cl = (RS_ConstructionLine*)e1; - - l1.setStartpoint(cl->getPoint1()); - l1.setEndpoint(cl->getPoint2()); - - te1 = &l1; - } - if (e2->rtti()==RS2::EntityConstructionLine) { - RS_ConstructionLine* cl = (RS_ConstructionLine*)e2; - - l2.setStartpoint(cl->getPoint1()); - l2.setEndpoint(cl->getPoint2()); - - te2 = &l2; - } - - - // convert circles to arcs: - if (e1->rtti()==RS2::EntityCircle) { - RS_Circle* c = (RS_Circle*)e1; - - RS_ArcData data(c->getCenter(), c->getRadius(), 0.0, 2*M_PI, false); - a1.setData(data); - - te1 = &a1; - } - if (e2->rtti()==RS2::EntityCircle) { - RS_Circle* c = (RS_Circle*)e2; - - RS_ArcData data(c->getCenter(), c->getRadius(), 0.0, 2*M_PI, false); - a2.setData(data); - - te2 = &a2; - } - - - // line / line: - // - //else - if (te1->rtti()==RS2::EntityLine && - te2->rtti()==RS2::EntityLine) { - - RS_Line* line1 = (RS_Line*)te1; - RS_Line* line2 = (RS_Line*)te2; - - ret = getIntersectionLineLine(line1, line2); - } - - // line / arc: - // - else if (te1->rtti()==RS2::EntityLine && - te2->rtti()==RS2::EntityArc) { - - RS_Line* line = (RS_Line*)te1; - RS_Arc* arc = (RS_Arc*)te2; - - ret = getIntersectionLineArc(line, arc); - } - - // arc / line: - // - else if (te1->rtti()==RS2::EntityArc && - te2->rtti()==RS2::EntityLine) { - - RS_Arc* arc = (RS_Arc*)te1; - RS_Line* line = (RS_Line*)te2; - - ret = getIntersectionLineArc(line, arc); - } - - // arc / arc: - // - else if (te1->rtti()==RS2::EntityArc && - te2->rtti()==RS2::EntityArc) { - - RS_Arc* arc1 = (RS_Arc*)te1; - RS_Arc* arc2 = (RS_Arc*)te2; - - ret = getIntersectionArcArc(arc1, arc2); - } else { - RS_DEBUG->print("RS_Information::getIntersection:: Unsupported entity type."); - } - } - - - // Check all intersection points for being on entities: - // - if (onEntities==true) { - if (!e1->isPointOnEntity(ret.get(0), tol) || - !e2->isPointOnEntity(ret.get(0), tol)) { - ret.set(0, Vector(false)); - } - if (!e1->isPointOnEntity(ret.get(1), tol) || - !e2->isPointOnEntity(ret.get(1), tol)) { - ret.set(1, Vector(false)); - } - if (!e1->isPointOnEntity(ret.get(2), tol) || - !e2->isPointOnEntity(ret.get(2), tol)) { - ret.set(2, Vector(false)); - } - if (!e1->isPointOnEntity(ret.get(3), tol) || - !e2->isPointOnEntity(ret.get(3), tol)) { - ret.set(3, Vector(false)); - } - } - - int k=0; - for (int i=0; i<4; ++i) { - if (ret.get(i).valid) { - ret.set(k, ret.get(i)); - k++; - } - } - for (int i=k; i<4; ++i) { - ret.set(i, Vector(false)); - } - - return ret; -} + // line / line: + // + //else + if (te1->rtti() == RS2::EntityLine && te2->rtti() == RS2::EntityLine) + { + RS_Line * line1 = (RS_Line *)te1; + RS_Line * line2 = (RS_Line *)te2; + ret = getIntersectionLineLine(line1, line2); + } + // line / arc: + // + else if (te1->rtti() == RS2::EntityLine && te2->rtti() == RS2::EntityArc) + { + RS_Line * line = (RS_Line *)te1; + RS_Arc * arc = (RS_Arc *)te2; + ret = getIntersectionLineArc(line, arc); + } + // arc / line: + // + else if (te1->rtti() == RS2::EntityArc && te2->rtti() == RS2::EntityLine) + { + RS_Arc * arc = (RS_Arc *)te1; + RS_Line * line = (RS_Line *)te2; + ret = getIntersectionLineArc(line, arc); + } + // arc / arc: + // + else if (te1->rtti() == RS2::EntityArc && te2->rtti() == RS2::EntityArc) + { + RS_Arc * arc1 = (RS_Arc *)te1; + RS_Arc * arc2 = (RS_Arc *)te2; + ret = getIntersectionArcArc(arc1, arc2); + } + else + { + RS_DEBUG->print("RS_Information::getIntersection:: Unsupported entity type."); + } + } + // Check all intersection points for being on entities: + // + if (onEntities) + { + if (!e1->isPointOnEntity(ret.get(0), tol) || !e2->isPointOnEntity(ret.get(0), tol)) + { + ret.set(0, Vector(false)); + } + if (!e1->isPointOnEntity(ret.get(1), tol) || !e2->isPointOnEntity(ret.get(1), tol)) + { + ret.set(1, Vector(false)); + } -/** - * @return Intersection between two lines. - */ -VectorSolutions RS_Information::getIntersectionLineLine(RS_Line* e1, - RS_Line* e2) { + if (!e1->isPointOnEntity(ret.get(2), tol) || !e2->isPointOnEntity(ret.get(2), tol)) + { + ret.set(2, Vector(false)); + } - VectorSolutions ret; + if (!e1->isPointOnEntity(ret.get(3), tol) || !e2->isPointOnEntity(ret.get(3), tol)) + { + ret.set(3, Vector(false)); + } + } - if (e1==NULL || e2==NULL) { - return ret; - } + int k = 0; + for(int i=0; i<4; ++i) + { + if (ret.get(i).valid) + { + ret.set(k, ret.get(i)); + k++; + } + } - Vector p1 = e1->getStartpoint(); - Vector p2 = e1->getEndpoint(); - Vector p3 = e2->getStartpoint(); - Vector p4 = e2->getEndpoint(); + for (int i=k; i<4; ++i) + { + ret.set(i, Vector(false)); + } - double num = ((p4.x-p3.x)*(p1.y-p3.y) - (p4.y-p3.y)*(p1.x-p3.x)); - double div = ((p4.y-p3.y)*(p2.x-p1.x) - (p4.x-p3.x)*(p2.y-p1.y)); + return ret; +} - if (fabs(div)>RS_TOLERANCE) { - double u = num / div; +/** + * @return Intersection between two lines. + */ +VectorSolutions RS_Information::getIntersectionLineLine(RS_Line * e1, RS_Line * e2) +{ + VectorSolutions ret; - double xs = p1.x + u * (p2.x-p1.x); - double ys = p1.y + u * (p2.y-p1.y); - ret = VectorSolutions(Vector(xs, ys)); - } + if (!e1 || !e2) + return ret; - // lines are parallel - else { - ret = VectorSolutions(); - } + Vector p1 = e1->getStartpoint(); + Vector p2 = e1->getEndpoint(); + Vector p3 = e2->getStartpoint(); + Vector p4 = e2->getEndpoint(); - return ret; -} + double num = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)); + double div = ((p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y)); + if (fabs(div) > RS_TOLERANCE) + { + double u = num / div; + double xs = p1.x + u * (p2.x - p1.x); + double ys = p1.y + u * (p2.y - p1.y); + ret = VectorSolutions(Vector(xs, ys)); + } + // lines are parallel + else + ret = VectorSolutions(); + return ret; +} /** * @return One or two intersection points between given entities. */ -VectorSolutions RS_Information::getIntersectionLineArc(RS_Line* line, - RS_Arc* arc) { - - VectorSolutions ret; - - if (line==NULL || arc==NULL) { - return ret; - } - - double dist=0.0; - Vector nearest; - nearest = line->getNearestPointOnEntity(arc->getCenter(), false, &dist); - - // special case: arc touches line (tangent): - if (fabs(dist - arc->getRadius()) < 1.0e-4) { - ret = VectorSolutions(nearest); - ret.setTangent(true); - return ret; - } - - Vector p = line->getStartpoint(); - Vector d = line->getEndpoint() - line->getStartpoint(); - if (d.magnitude()<1.0e-6) { - return ret; - } - - Vector c = arc->getCenter(); - double r = arc->getRadius(); - Vector delta = p - c; - - // root term: - double term = RS_Math::pow(Vector::dotP(d, delta), 2.0) - - RS_Math::pow(d.magnitude(), 2.0) - * (RS_Math::pow(delta.magnitude(), 2.0) - RS_Math::pow(r, 2.0)); - - // no intersection: - if (term<0.0) { - VectorSolutions s; - ret = s; - } - - // one or two intersections: - else { - double t1 = (- Vector::dotP(d, delta) + sqrt(term)) - / RS_Math::pow(d.magnitude(), 2.0); - double t2; - bool tangent = false; - - // only one intersection: - if (fabs(term)getNearestPointOnEntity(arc->getCenter(), false, &dist); + // special case: arc touches line (tangent): + if (fabs(dist - arc->getRadius()) < 1.0e-4) { + ret = VectorSolutions(nearest); + ret.setTangent(true); + return ret; + } -/** - * @return One or two intersection points between given entities. - */ -VectorSolutions RS_Information::getIntersectionArcArc(RS_Arc* e1, - RS_Arc* e2) { + Vector p = line->getStartpoint(); + Vector d = line->getEndpoint() - line->getStartpoint(); + if (d.magnitude()<1.0e-6) { + return ret; + } + + Vector c = arc->getCenter(); + double r = arc->getRadius(); + Vector delta = p - c; - VectorSolutions ret; + // root term: + double term = RS_Math::pow(Vector::dotP(d, delta), 2.0) + - RS_Math::pow(d.magnitude(), 2.0) + * (RS_Math::pow(delta.magnitude(), 2.0) - RS_Math::pow(r, 2.0)); + + // no intersection: + if (term<0.0) { + VectorSolutions s; + ret = s; + } - if (e1==NULL || e2==NULL) { - return ret; - } + // one or two intersections: + else { + double t1 = (- Vector::dotP(d, delta) + sqrt(term)) + / RS_Math::pow(d.magnitude(), 2.0); + double t2; + bool tangent = false; + + // only one intersection: + if (fabs(term)getCenter(); - Vector c2 = e2->getCenter(); + ret = VectorSolutions(sol1, sol2); + ret.setTangent(tangent); + } - double r1 = e1->getRadius(); - double r2 = e2->getRadius(); + return ret; +} - Vector u = c2 - c1; +/** + * @return One or two intersection points between given entities. + */ +VectorSolutions RS_Information::getIntersectionArcArc(RS_Arc * e1, RS_Arc * e2) +{ + VectorSolutions ret; - // concentric - if (u.magnitude()<1.0e-6) { - return ret; - } + if (e1==NULL || e2==NULL) { + return ret; + } - Vector v = Vector(u.y, -u.x); + Vector c1 = e1->getCenter(); + Vector c2 = e2->getCenter(); - double s, t1, t2, term; + double r1 = e1->getRadius(); + double r2 = e2->getRadius(); - s = 1.0/2.0 * ((r1*r1 - r2*r2)/(RS_Math::pow(u.magnitude(), 2.0)) + 1.0); + Vector u = c2 - c1; - term = (r1*r1)/(RS_Math::pow(u.magnitude(), 2.0)) - s*s; + // concentric + if (u.magnitude()<1.0e-6) { + return ret; + } - // no intersection: - if (term<0.0) { - ret = VectorSolutions(); - } + Vector v = Vector(u.y, -u.x); - // one or two intersections: - else { - t1 = sqrt(term); - t2 = -sqrt(term); - bool tangent = false; + double s, t1, t2, term; - Vector sol1 = c1 + u*s + v*t1; - Vector sol2 = c1 + u*s + v*t2; + s = 1.0/2.0 * ((r1*r1 - r2*r2)/(RS_Math::pow(u.magnitude(), 2.0)) + 1.0); - if (sol1.distanceTo(sol2)<1.0e-4) { - sol2 = Vector(false); - ret = VectorSolutions(sol1); - tangent = true; - } else { - ret = VectorSolutions(sol1, sol2); - } + term = (r1*r1)/(RS_Math::pow(u.magnitude(), 2.0)) - s*s; - ret.setTangent(tangent); - } + // no intersection: + if (term<0.0) { + ret = VectorSolutions(); + } - return ret; -} + // one or two intersections: + else { + t1 = sqrt(term); + t2 = -sqrt(term); + bool tangent = false; + + Vector sol1 = c1 + u*s + v*t1; + Vector sol2 = c1 + u*s + v*t2; + + if (sol1.distanceTo(sol2)<1.0e-4) { + sol2 = Vector(false); + ret = VectorSolutions(sol1); + tangent = true; + } else { + ret = VectorSolutions(sol1, sol2); + } + ret.setTangent(tangent); + } + return ret; +} /** * @return One or two intersection points between given entities. */ -VectorSolutions RS_Information::getIntersectionLineEllipse(RS_Line* line, - RS_Ellipse* ellipse) { - - VectorSolutions ret; - - if (line==NULL || ellipse==NULL) { - return ret; - } - - // rotate into normal position: - double ang = ellipse->getAngle(); - - double rx = ellipse->getMajorRadius(); - double ry = ellipse->getMinorRadius(); - Vector center = ellipse->getCenter(); - Vector a1 = line->getStartpoint().rotate(center, -ang); - Vector a2 = line->getEndpoint().rotate(center, -ang); - Vector origin = a1; - Vector dir = a2-a1; - Vector diff = origin - center; - Vector mDir = Vector(dir.x/(rx*rx), dir.y/(ry*ry)); - Vector mDiff = Vector(diff.x/(rx*rx), diff.y/(ry*ry)); - - double a = Vector::dotP(dir, mDir); - double b = Vector::dotP(dir, mDiff); - double c = Vector::dotP(diff, mDiff) - 1.0; - double d = b*b - a*c; - - if (d < 0) { - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 0"); - } else if ( d > 0 ) { - double root = sqrt(d); - double t_a = (-b - root) / a; - double t_b = (-b + root) / a; - - /*if ( (t_a < 0 || 1 < t_a) && (t_b < 0 || 1 < t_b) ) { - if ( (t_a < 0 && t_b < 0) || (t_a > 1 && t_b > 1) ) { - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 1"); - } - else { - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: inside 1"); - } - } else {*/ - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: intersection 1"); - Vector ret1(false); - Vector ret2(false); - //if ( 0 <= t_a && t_a <= 1 ) { - //RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t_a<=1"); - ret1 = a1.lerp(a2, t_a); - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret1: %f/%f", ret1.x, ret1.y); - //} - //if ( 0 <= t_b && t_b <= 1 ) { - //RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t_b<=1"); - ret2 = a1.lerp(a2, t_b); - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret2: %f/%f", ret2.x, ret2.y); - //} - if (ret1.valid && ret2.valid) { - ret = VectorSolutions(ret1, ret2); - } - else { - if (ret1.valid) { - ret = VectorSolutions(ret1); - } - if (ret2.valid) { - ret = VectorSolutions(ret2); - } - } - //} - } else { - double t = -b/a; - if ( 0 <= t && t <= 1 ) { - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t<=1"); - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: intersection 2"); - ret = VectorSolutions(a1.lerp(a2, t)); - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret1: %f/%f", ret.get(0).x, ret.get(0).y); - } else { - RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 2"); - } - } - - ret.rotate(center, ang); - return ret; - - - - /* - RS_Arc* arc = new RS_Arc(NULL, - RS_ArcData(ellipse->getCenter(), - ellipse->getMajorRadius(), - ellipse->getAngle1(), - ellipse->getAngle2(), - false)); - RS_Line* other = (RS_Line*)line->clone(); - double angle = ellipse->getAngle(); - //double ratio = ellipse->getRatio(); - - // rotate entities: - other->rotate(ellipse->getCenter(), -angle); - other->scale(ellipse->getCenter(), Vector(1.0, 1.0/ellipse->getRatio())); - - ret = getIntersectionLineArc(other, arc); - - ret.scale(ellipse->getCenter(), Vector(1.0, ellipse->getRatio())); - ret.rotate(ellipse->getCenter(), angle); - - delete arc; - delete other; - - return ret; - */ -} +VectorSolutions RS_Information::getIntersectionLineEllipse(RS_Line * line, RS_Ellipse * ellipse) +{ + VectorSolutions ret; + if (line==NULL || ellipse==NULL) { + return ret; + } + + // rotate into normal position: + double ang = ellipse->getAngle(); + + double rx = ellipse->getMajorRadius(); + double ry = ellipse->getMinorRadius(); + Vector center = ellipse->getCenter(); + Vector a1 = line->getStartpoint().rotate(center, -ang); + Vector a2 = line->getEndpoint().rotate(center, -ang); + Vector origin = a1; + Vector dir = a2-a1; + Vector diff = origin - center; + Vector mDir = Vector(dir.x/(rx*rx), dir.y/(ry*ry)); + Vector mDiff = Vector(diff.x/(rx*rx), diff.y/(ry*ry)); + + double a = Vector::dotP(dir, mDir); + double b = Vector::dotP(dir, mDiff); + double c = Vector::dotP(diff, mDiff) - 1.0; + double d = b*b - a*c; + + if (d < 0) { + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 0"); + } else if ( d > 0 ) { + double root = sqrt(d); + double t_a = (-b - root) / a; + double t_b = (-b + root) / a; + + /*if ( (t_a < 0 || 1 < t_a) && (t_b < 0 || 1 < t_b) ) { + if ( (t_a < 0 && t_b < 0) || (t_a > 1 && t_b > 1) ) { + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 1"); + } + else { + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: inside 1"); + } + } else {*/ + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: intersection 1"); + Vector ret1(false); + Vector ret2(false); + //if ( 0 <= t_a && t_a <= 1 ) { + //RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t_a<=1"); + ret1 = a1.lerp(a2, t_a); + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret1: %f/%f", ret1.x, ret1.y); + //} + //if ( 0 <= t_b && t_b <= 1 ) { + //RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t_b<=1"); + ret2 = a1.lerp(a2, t_b); + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret2: %f/%f", ret2.x, ret2.y); + //} + if (ret1.valid && ret2.valid) { + ret = VectorSolutions(ret1, ret2); + } + else { + if (ret1.valid) { + ret = VectorSolutions(ret1); + } + if (ret2.valid) { + ret = VectorSolutions(ret2); + } + } + //} + } else { + double t = -b/a; + if ( 0 <= t && t <= 1 ) { + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t<=1"); + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: intersection 2"); + ret = VectorSolutions(a1.lerp(a2, t)); + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret1: %f/%f", ret.get(0).x, ret.get(0).y); + } else { + RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 2"); + } + } + + ret.rotate(center, ang); + return ret; + + + + /* + RS_Arc* arc = new RS_Arc(NULL, + RS_ArcData(ellipse->getCenter(), + ellipse->getMajorRadius(), + ellipse->getAngle1(), + ellipse->getAngle2(), + false)); + RS_Line* other = (RS_Line*)line->clone(); + double angle = ellipse->getAngle(); + //double ratio = ellipse->getRatio(); + + // rotate entities: + other->rotate(ellipse->getCenter(), -angle); + other->scale(ellipse->getCenter(), Vector(1.0, 1.0/ellipse->getRatio())); + + ret = getIntersectionLineArc(other, arc); + + ret.scale(ellipse->getCenter(), Vector(1.0, ellipse->getRatio())); + ret.rotate(ellipse->getCenter(), angle); + + delete arc; + delete other; + + return ret; + */ +} /** * Checks if the given coordinate is inside the given contour. @@ -672,151 +651,175 @@ VectorSolutions RS_Information::getIntersectionLineEllipse(RS_Line* line, * @param onContour Will be set to true if the given point it exactly * on the contour. */ -bool RS_Information::isPointInsideContour(const Vector& point, - RS_EntityContainer* contour, bool* onContour) { - - if (contour==NULL) { - RS_DEBUG->print(RS_Debug::D_WARNING, +bool RS_Information::isPointInsideContour(const Vector & point, + RS_EntityContainer * contour, bool * onContour) +{ + if (contour==NULL) { + RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Information::isPointInsideContour: contour is NULL"); - return false; - } - - if (point.x < contour->getMin().x || point.x > contour->getMax().x || - point.y < contour->getMin().y || point.y > contour->getMax().y) { - return false; - } - - double width = contour->getSize().x+1.0; - - bool sure; - int counter; - int tries = 0; - double rayAngle = 0.0; - do { - sure = true; - - // create ray: - Vector v; - v.setPolar(width*10.0, rayAngle); - RS_Line ray(NULL, RS_LineData(point, point+v)); - counter = 0; - VectorSolutions sol; - - if (onContour!=NULL) { - *onContour = false; - } - - for (RS_Entity* e = contour->firstEntity(RS2::ResolveAll); - e!=NULL; - e = contour->nextEntity(RS2::ResolveAll)) { - - // intersection(s) from ray with contour entity: - sol = RS_Information::getIntersection(&ray, e, true); - - for (int i=0; i<=1; ++i) { - Vector p = sol.get(i); - - if (p.valid) { - // point is on the contour itself - if (p.distanceTo(point)<1.0e-5) { - if (onContour!=NULL) { - *onContour = true; - } - } else { - if (e->rtti()==RS2::EntityLine) { - RS_Line* line = (RS_Line*)e; - - // ray goes through startpoint of line: - if (p.distanceTo(line->getStartpoint())<1.0e-4) { - if (RS_Math::correctAngle(line->getAngle1())getEndpoint())<1.0e-4) { - if (RS_Math::correctAngle(line->getAngle2())rtti()==RS2::EntityArc) { - RS_Arc* arc = (RS_Arc*)e; - - if (p.distanceTo(arc->getStartpoint())<1.0e-4) { - double dir = arc->getDirection1(); - if ((dir=1.0e-5) || - ((dir>2*M_PI-1.0e-5 || dir<1.0e-5) && - arc->getCenter().y>p.y)) { - counter++; - sure = false; - } - } - else if (p.distanceTo(arc->getEndpoint())<1.0e-4) { - double dir = arc->getDirection2(); - if ((dir=1.0e-5) || - ((dir>2*M_PI-1.0e-5 || dir<1.0e-5) && - arc->getCenter().y>p.y)) { - counter++; - sure = false; - } - } else { - counter++; - } - } else if (e->rtti()==RS2::EntityCircle) { - // tangent: - if (i==0 && sol.get(1).valid==false) { - if (!sol.isTangent()) { - counter++; - } else { - sure = false; - } - } else if (i==1 || sol.get(1).valid==true) { - counter++; - } - } - } - } - } - } - - rayAngle+=0.02; - tries++; - } - while (!sure && rayAngle<2*M_PI && tries<6); - - // remove double intersections: - /* - Q3PtrList is2; - bool done; - Vector* av; - do { - done = true; - double minDist = RS_MAXDOUBLE; - double dist; - av = NULL; - for (Vector* v = is.first(); v!=NULL; v = is.next()) { - dist = point.distanceTo(*v); - if (distgetMin().x || point.x > contour->getMax().x || + point.y < contour->getMin().y || point.y > contour->getMax().y) + return false; + + double width = contour->getSize().x+1.0; + bool sure; + int counter; + int tries = 0; + double rayAngle = 0.0; + + do + { + sure = true; + + // create ray: + Vector v; + v.setPolar(width*10.0, rayAngle); + RS_Line ray(NULL, RS_LineData(point, point+v)); + counter = 0; + VectorSolutions sol; + + if (onContour) + *onContour = false; + + for(RS_Entity * e=contour->firstEntity(RS2::ResolveAll); e!=NULL; + e=contour->nextEntity(RS2::ResolveAll)) + { + // intersection(s) from ray with contour entity: + sol = RS_Information::getIntersection(&ray, e, true); + + for(int i=0; i<=1; ++i) + { + Vector p = sol.get(i); + + if (p.valid) + { + // point is on the contour itself + if (p.distanceTo(point) < 1.0e-5) + { + if (onContour) + { + *onContour = true; + } + } + else + { + if (e->rtti() == RS2::EntityLine) + { + RS_Line * line = (RS_Line *)e; + + // ray goes through startpoint of line: + if (p.distanceTo(line->getStartpoint()) < 1.0e-4) + { + if (RS_Math::correctAngle(line->getAngle1()) < M_PI) + { + counter++; + sure = false; + } + } + // ray goes through endpoint of line: + else if (p.distanceTo(line->getEndpoint()) < 1.0e-4) + { + if (RS_Math::correctAngle(line->getAngle2()) < M_PI) + { + counter++; + sure = false; + } + } + // ray goes through the line: + else + { + counter++; + } + } + else if (e->rtti() == RS2::EntityArc) + { + RS_Arc * arc = (RS_Arc *)e; + + if (p.distanceTo(arc->getStartpoint()) < 1.0e-4) + { + double dir = arc->getDirection1(); + + if ((dir < M_PI && dir >= 1.0e-5) + || ((dir > 2 * M_PI - 1.0e-5 || dir < 1.0e-5) + && arc->getCenter().y > p.y)) + { + counter++; + sure = false; + } + } + else if (p.distanceTo(arc->getEndpoint()) < 1.0e-4) + { + double dir = arc->getDirection2(); + + if ((dir < M_PI && dir >= 1.0e-5) + || ((dir > 2 * M_PI - 1.0e-5 || dir < 1.0e-5) + && arc->getCenter().y>p.y)) + { + counter++; + sure = false; + } + } + else + { + counter++; + } + } + else if (e->rtti() == RS2::EntityCircle) + { + // tangent: + if (i == 0 && sol.get(1).valid == false) + { + if (!sol.isTangent()) + { + counter++; + } + else + { + sure = false; + } + } + else if (i == 1 || sol.get(1).valid) + { + counter++; + } + } + } + } + } + } + + rayAngle += 0.02; + tries++; + } + while (!sure && rayAngle < 2 * M_PI && tries < 6); + + // remove double intersections: + /* + Q3PtrList is2; + bool done; + Vector* av; + do { + done = true; + double minDist = RS_MAXDOUBLE; + double dist; + av = NULL; + for (Vector* v = is.first(); v!=NULL; v = is.next()) { + dist = point.distanceTo(*v); + if (dist