/** * Creates an arc from 3 points. */ RArc RArc::createFrom3Points(const RVector& startPoint, const RVector& point, const RVector& endPoint) { // intersection of two middle lines // middle points between first two points: RVector mp1 = RVector::getAverage(startPoint, point); double a1 = startPoint.getAngleTo(point) + M_PI / 2.0; // direction from middle point to center: RVector dir1 = RVector::createPolar(1.0, a1); // middle points between last two points: RVector mp2 = RVector::getAverage(point, endPoint); double a2 = point.getAngleTo(endPoint) + M_PI / 2.0; // direction from middle point to center: RVector dir2 = RVector::createPolar(1.0, a2); RLine midLine1(mp1, mp1 + dir1); RLine midLine2(mp2, mp2 + dir2); QList<RVector> ips = midLine1.getIntersectionPoints(midLine2, false); if (ips.length()!=1) { //this.error = qsTr("No arc possible"); return RArc(); } RVector center = ips[0]; double radius = center.getDistanceTo(endPoint); double angle1 = center.getAngleTo(startPoint); double angle2 = center.getAngleTo(endPoint); bool reversed = RMath::isAngleBetween(center.getAngleTo(point), angle1, angle2, true); return RArc(center, radius, angle1, angle2, reversed); }
void RExporter::exportArc(const RArc& arc, double offset) { if (!arc.isValid()) { return; } RLinetypePattern p = getLinetypePattern(); if (getEntity() == NULL || !p.isValid() || p.getNumDashes() == 1 || draftMode || screenBasedLinetypes) { exportArcSegment(arc); return; } RArc normalArc = arc; if (arc.isReversed()) { normalArc.reverse(); } if (normalArc.radius < 1.0e-12) { return; } p.scale(getPatternFactor()); double length = normalArc.getLength(); double patternLength = p.getPatternLength(); // avoid huge number of small segments due to very fine // pattern or long lines: if (patternLength<RS::PointTolerance || length / patternLength > 5000) { exportArcSegment(arc); return; } double* vp = NULL; vp = new double[p.getNumDashes()]; for (int i = 0; i < p.getNumDashes(); ++i) { vp[i] = fabs(p.getDashLengthAt(i)) / normalArc.radius; } if (RMath::isNaN(offset)) { offset = getPatternOffset(length, p); } QList<RArc> arcSegments; bool done = false; int i = 0; double cursor = normalArc.getStartAngle() + offset / normalArc.radius; double total = offset; bool dashFound = false; bool gapFound = false; double a1 = normalArc.getStartAngle(); double a2; do { if (dashFound && !gapFound) { if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) { arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, normalArc.getEndAngle())); break; } arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, a2)); } if (p.getDashLengthAt(i) > 0) { // dash, no gap if (total + p.getDashLengthAt(i) > 0) { a1 = cursor; if (total < 0 || !dashFound) { a1 = normalArc.startAngle; } a2 = cursor + vp[i]; if (fabs(a2 - normalArc.getStartAngle()) > 1.0e-6) { dashFound = true; } } gapFound = false; } else { gapFound = true; } cursor += vp[i]; total += fabs(p.getDashLengthAt(i)); done = total > length; ++i; if (i >= p.getNumDashes()) { i = 0; } } while (!done); if (!gapFound || !dashFound) { if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) { arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, normalArc.getEndAngle())); } else { arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, a2)); } } if (arc.isReversed()) { for (int i=arcSegments.length()-1; i>=0; i--) { arcSegments[i].reverse(); exportArcSegment(arcSegments[i]); } } else { for (int i=0; i<arcSegments.length(); i++) { exportArcSegment(arcSegments[i]); } } delete[] vp; }