bool RExporter::exportLinetypeShape(QList<RPainterPath>& pps, const RLine& line, double total, double length, double angle, const RVector& cursor) { RVector min = RPainterPath::getMinList(pps); RVector max = RPainterPath::getMaxList(pps); bool isCursorOnLine = line.isOnShape(cursor); double diffBefore = total+min.x; double diffAfter = total+max.x-length; bool shapeOutsideBefore = diffBefore < -RS::PointTolerance; bool shapeOutsideAfter = diffAfter > RS::PointTolerance; if (isCursorOnLine && (!shapeOutsideBefore && !shapeOutsideAfter)) { exportPainterPaths(pps, angle, cursor); return true; } else { if (shapeOutsideBefore) { // check if first shape is not entirely before the start point of the line: if (total + max.x < 0.0) { return false; } RLine l = line; if (fabs(total+max.x)<length) { RVector p = RVector( cos(angle) * fabs(total+max.x), sin(angle) * fabs(total+max.x) ); l.endPoint = l.startPoint + p; } exportLineSegment(l, angle); return true; } if (shapeOutsideAfter) { // check if last shape is not entirely after the end point of the line: if (total + min.x > length) { return false; } RLine l = line; if (fabs(total+min.x)>0.0) { RVector p = RVector( cos(angle) * fabs(total+min.x), sin(angle) * fabs(total+min.x) ); l.startPoint = l.startPoint + p; } exportLineSegment(l, angle); return true; } return false; } }
QList<RVector> RShape::getIntersectionPointsLL(const RLine& line1, const RLine& line2, bool limited1, bool limited2) { QList<RVector> res; double a1 = line1.endPoint.y - line1.startPoint.y; double b1 = line1.startPoint.x - line1.endPoint.x; double c1 = a1 * line1.startPoint.x + b1 * line1.startPoint.y; double a2 = line2.endPoint.y - line2.startPoint.y; double b2 = line2.startPoint.x - line2.endPoint.x; double c2 = a2 * line2.startPoint.x + b2 * line2.startPoint.y; double det = a1 * b2 - a2 * b1; if (fabs(det) < 1.0e-6) { return res; } else { RVector v((b2 * c1 - b1 * c2) / det, (a1 * c2 - a2 * c1) / det); if ((!limited1 || line1.isOnShape(v)) && (!limited2 || line2.isOnShape(v))) { res.append(v); return res; } } return res; }
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; }
QList<RVector> RShape::getIntersectionPointsLC(const RLine& line1, const RCircle& circle2, bool limited) { QList<RVector> res; RVector vLineCenter = line1.getVectorTo(circle2.getCenter(), false); double dist = vLineCenter.getMagnitude(); // special case: arc touches line (tangent): if (fabs(dist - circle2.getRadius()) < 1.0e-4) { res.append(circle2.getCenter() - vLineCenter); // ret.setTangent(true); return res; } RVector p = line1.getStartPoint(); RVector d = line1.getEndPoint() - line1.getStartPoint(); if (d.getMagnitude() < 1.0e-6) { return res; } RVector delta = p - circle2.getCenter(); // root term: double term = RMath::pow(RVector::getDotProduct(d, delta), 2.0) - RMath::pow(d.getMagnitude(), 2.0) * (RMath::pow(delta.getMagnitude(), 2.0) - RMath::pow(circle2.getRadius(), 2.0)); // no intersection: if (term<0.0) { return res; } // one or two intersections: double t1 = (- RVector::getDotProduct(d, delta) + sqrt(term)) / RMath::pow(d.getMagnitude(), 2.0); double t2; bool tangent = false; // only one intersection: if (fabs(term) < RS::PointTolerance) { t2 = t1; tangent = true; } // two intersections else { t2 = (-RVector::getDotProduct(d, delta) - sqrt(term)) / RMath::pow(d.getMagnitude(), 2.0); } RVector sol1; RVector sol2 = RVector::invalid; sol1 = p + d * t1; if (!tangent) { sol2 = p + d * t2; } if (!limited || line1.isOnShape(sol1)) { res.append(sol1); } if (sol2.isValid()) { if (!limited || line1.isOnShape(sol2)) { res.append(sol2); } } // ret.setTangent(tangent); return res; }