QList<RVector> RShape::getIntersectionPointsAE(const RArc& arc1, const REllipse& ellipse2, bool limited) { QList<RVector> candidates = RShape::getIntersectionPointsCE( RCircle(arc1.getCenter(), arc1.getRadius()), ellipse2); if (!limited) { return candidates; } QList<RVector> res; for (int i=0; i<candidates.count(); i++) { RVector c = candidates[i]; if (arc1.isOnShape(c)) { if (!ellipse2.isFullEllipse()) { double a1 = ellipse2.getCenter().getAngleTo(ellipse2.getStartPoint()); double a2 = ellipse2.getCenter().getAngleTo(ellipse2.getEndPoint()); double a = ellipse2.getCenter().getAngleTo(c); if (!RMath::isAngleBetween(a, a1, a2, ellipse2.isReversed())) { continue; } } res.append(c); } } return res; }
void REllipseEntity::setShape(const REllipse& e) { data.setCenter(e.getCenter()); data.setMajorPoint(e.getMajorPoint()); data.setRatio(e.getRatio()); data.setStartParam(e.getStartParam()); data.setEndParam(e.getEndParam()); data.setReversed(e.isReversed()); }
/** * Exports an ellipse with the current attributes. * \todo switch from line based interpolation to arcs. */ void RExporter::exportEllipse(const REllipse& ellipse, double offset) { if (ellipse.getMajorRadius()<RS::PointTolerance || ellipse.getMinorRadius()<RS::PointTolerance) { return; } RPolyline polyline; RVector cp = ellipse.getCenter(); double radius1 = ellipse.getMajorRadius(); double radius2 = ellipse.getMinorRadius(); double angle = ellipse.getAngle(); double a1 = ellipse.getStartParam(); double a2 = ellipse.getEndParam(); bool reversed = ellipse.isReversed(); double aStep; // Angle Step (rad) double a; // Current Angle (rad) aStep=0.05; RVector vp; RVector vc(cp.x, cp.y); vp.set(cp.x+cos(a1)*radius1, cp.y+sin(a1)*radius2); vp.rotate(angle, vc); polyline.appendVertex(vp); if (!reversed) { // Arc Counterclockwise: if (a1>a2-RS::AngleTolerance) { a2+=2*M_PI; } for(a=a1+aStep; a<=a2; a+=aStep) { vp.set(cp.x+cos(a)*radius1, cp.y+sin(a)*radius2); vp.rotate(angle, vc); polyline.appendVertex(vp); } } else { // Arc Clockwise: if (a1<a2+RS::AngleTolerance) { a2-=2*M_PI; } for(a=a1-aStep; a>=a2; a-=aStep) { vp.set(cp.x+cos(a)*radius1, cp.y+sin(a)*radius2); vp.rotate(angle, vc); polyline.appendVertex(vp); } } vp.set(cp.x+cos(a2)*radius1, cp.y+sin(a2)*radius2); vp.rotate(angle, vc); polyline.appendVertex(vp); exportPolyline(polyline, offset); }
QList<RVector> RShape::getIntersectionPointsEE(const REllipse& ellipse1, const REllipse& ellipse2, bool limited) { QList<RVector> candidates = getIntersectionPointsEE(ellipse1, ellipse2); if (!limited) { return candidates; } QList<RVector> ret; for (int i=0; i<candidates.length(); i++) { RVector c = candidates[i]; bool onShape = true; double a1 = ellipse1.getCenter().getAngleTo(ellipse1.getStartPoint()); double a2 = ellipse1.getCenter().getAngleTo(ellipse1.getEndPoint()); double a = ellipse1.getCenter().getAngleTo(c); if (!RMath::isAngleBetween(a, a1, a2, ellipse1.isReversed())) { // qDebug() << "1) angle NOT between: " // << " a: " << RMath::rad2deg(a) // << " a1: " << RMath::rad2deg(a1) // << " a2: " << RMath::rad2deg(a2) // << " r: " << ellipse1.isReversed(); //ret.append(c); onShape = false; } a1 = ellipse2.getCenter().getAngleTo(ellipse2.getStartPoint()); a2 = ellipse2.getCenter().getAngleTo(ellipse2.getEndPoint()); a = ellipse2.getCenter().getAngleTo(c); if (!RMath::isAngleBetween(a, a1, a2, ellipse2.isReversed())) { // qDebug() << "2) angle NOT between: " // << " a: " << RMath::rad2deg(a) // << " a1: " << RMath::rad2deg(a1) // << " a2: " << RMath::rad2deg(a2) // << " r: " << ellipse2.isReversed(); //ret.append(c); onShape = false; } if (onShape) { ret.append(c); } } return ret; }
QList<RVector> RShape::getIntersectionPointsLE(const RLine& line1, const REllipse& ellipse2, bool limited) { QList<RVector> res; // find out if line1 is (almost) a tangent: QList<RLine> tangents = ellipse2.getTangents(line1.getMiddlePoint()); for (int i=0; i<tangents.length(); i++) { double a = tangents[i].getAngle(); double ad1 = fabs(RMath::getAngleDifference180(a, line1.getDirection1())); double ad2 = fabs(RMath::getAngleDifference180(a, line1.getDirection2())); if (ad1 < 1.0e-2 || ad2 < 1.0e-2) { res.append(tangents[i].getEndPoint()); // no need to continue: max. one tangent possible: return res; } } // rotate into normal position: double ang = ellipse2.getAngle(); double rx = ellipse2.getMajorRadius(); double ry = ellipse2.getMinorRadius(); RVector center = ellipse2.getCenter(); RVector a1 = line1.getStartPoint(); a1.rotate(-ang, center); RVector a2 = line1.getEndPoint(); a2.rotate(-ang, center); RVector origin = a1; RVector dir = a2-a1; RVector diff = origin - center; RVector mDir = RVector(dir.x/(rx*rx), dir.y/(ry*ry)); RVector mDiff = RVector(diff.x/(rx*rx), diff.y/(ry*ry)); double a = RVector::getDotProduct(dir, mDir); double b = RVector::getDotProduct(dir, mDiff); double c = RVector::getDotProduct(diff, mDiff) - 1.0; double d = b*b - a*c; RVector res1 = RVector::invalid; RVector res2 = RVector::invalid; if (d < 0) { // no solution } else if ( d > 0 ) { double root = sqrt(d); double t_a = (-b - root) / a; double t_b = (-b + root) / a; res1 = a1.getLerp(a2, t_a).rotate(ang, center); res2 = a1.getLerp(a2, t_b).rotate(ang, center); } else { double t = -b/a; if ( 0 <= t && t <= 1 ) { // one solution: res1 = a1.getLerp(a2, t).rotate(ang, center); } else { // no solution } } if (res1.isValid()) { if (!limited || (line1.isOnShape(res1) && ellipse2.isOnShape(res1))) { res.append(res1); } } if (res2.isValid()) { if (!limited || (line1.isOnShape(res2) && ellipse2.isOnShape(res2))) { res.append(res2); } } return res; }