// previously: getEllipseAngle double REllipse::getParamTo(const RVector& pos) const { RVector m = pos; m.rotate(-majorPoint.getAngle(), center); RVector v = m-center; v.scale(RVector(1.0, 1.0/ratio)); return v.getAngle(); }
RVector RCircle::getVectorTo(const RVector& point, bool /*limited*/) const { RVector v = point - center; // point is at the center of the circle, infinite solutions: if (v.getMagnitude()<RS::PointTolerance) { return RVector::invalid; } return RVector::createPolar(v.getMagnitude() - radius, v.getAngle()); }
RVector RArc::getVectorTo(const RVector& point, bool limited) const { double angle = center.getAngleTo(point); if (limited && !RMath::isAngleBetween(angle, startAngle, endAngle, reversed)) { return RVector::invalid; } RVector v = point - center; return RVector::createPolar(v.getMagnitude() - radius, v.getAngle()); }
bool RArc::mirror(const RLine& axis) { center.mirror(axis); if (isFullCircle()) { return true; } reversed = (!reversed); RVector v; v.setPolar(1.0, startAngle); v.mirror(RVector(0.0, 0.0), axis.endPoint - axis.startPoint); startAngle = v.getAngle(); v.setPolar(1.0, endAngle); v.mirror(RVector(0.0, 0.0), axis.endPoint - axis.startPoint); endAngle = v.getAngle(); return true; }
bool RDimRotatedData::mirror(const RLine& axis) { RDimLinearData::mirror(axis); //extensionPoint1.mirror(axis); //extensionPoint2.mirror(axis); RLine neutralAxis = axis; neutralAxis.move(-neutralAxis.getStartPoint()); RVector vec = RVector::createPolar(1.0, rotation); vec.mirror(neutralAxis); rotation = vec.getAngle(); update(); return true; }
RVector REllipse::getVectorTo(const RVector& point, bool limited, double strictRange) const { Q_UNUSED(strictRange) RVector ret = RVector::invalid; double ang = getAngle(); //double dDistance = RMAXDOUBLE; bool swap = false; bool majorSwap = false; RVector normalized = (point - center).rotate(-ang); // special case: point in line with major axis: if (fabs(normalized.getAngle()) < RS::AngleTolerance || fabs(normalized.getAngle()) > 2*M_PI-RS::AngleTolerance) { ret = RVector(getMajorRadius(), 0.0); //dDistance = ret.distanceTo(normalized); } else if (fabs(normalized.getAngle()-M_PI) < RS::AngleTolerance) { ret = RVector(-getMajorRadius(), 0.0); //dDistance = ret.distanceTo(normalized); } else { double dU = normalized.x; double dV = normalized.y; double dA = getMajorRadius(); double dB = getMinorRadius(); double dEpsilon = 1.0e-8; // iteration maximum int iMax = 32; double rdX = 0.0; double rdY = 0.0; if (dA<dB) { double dum = dA; dA = dB; dB = dum; dum = dU; dU = dV; dV = dum; majorSwap = true; } if (dV<0.0) { dV*=-1.0; swap = true; } // initial guess: double dT = dB*(dV - dB); // newton's method: int i; for (i = 0; i < iMax; i++) { double dTpASqr = dT + dA*dA; double dTpBSqr = dT + dB*dB; double dInvTpASqr = 1.0/dTpASqr; double dInvTpBSqr = 1.0/dTpBSqr; double dXDivA = dA*dU*dInvTpASqr; double dYDivB = dB*dV*dInvTpBSqr; double dXDivASqr = dXDivA*dXDivA; double dYDivBSqr = dYDivB*dYDivB; double dF = dXDivASqr + dYDivBSqr - 1.0; if (fabs(dF) < dEpsilon) { // f(t0) is very close to zero: rdX = dXDivA*dA; rdY = dYDivB*dB; break; } double dFDer = 2.0*(dXDivASqr*dInvTpASqr + dYDivBSqr*dInvTpBSqr); double dRatio = dF/dFDer; if ( fabs(dRatio) < dEpsilon ) { // t1-t0 is very close to zero: rdX = dXDivA*dA; rdY = dYDivB*dB; break; } dT += dRatio; } if (i == iMax) { // failed to converge: //dDistance = RMAXDOUBLE; ret = RVector::invalid; } else { //double dDelta0 = rdX - dU; //double dDelta1 = rdY - dV; //dDistance = sqrt(dDelta0*dDelta0 + dDelta1*dDelta1); ret = RVector(rdX, rdY); } } if (ret.isValid()) { if (swap) { ret.y*=-1.0; } if (majorSwap) { double dum = ret.x; ret.x = ret.y; ret.y = dum; } ret = (ret.rotate(ang) + center); if (limited) { double a1 = center.getAngleTo(getStartPoint()); double a2 = center.getAngleTo(getEndPoint()); double a = center.getAngleTo(ret); if (!RMath::isAngleBetween(a, a1, a2, reversed)) { ret = RVector::invalid; } } } /* if (dist!=NULL) { if (ret.valid) { *dist = dDistance; } else { *dist = RS_MAXDOUBLE; } } if (entity!=NULL) { if (ret.valid) { *entity = this; } else { *entity = NULL; } } */ return point - ret; }
/** * Sets the minor point relative to the center point. */ void REllipse::setMinorPoint(const RVector& p) { double angle = RMath::getNormalizedAngle(p.getAngle() - M_PI/2.0); majorPoint.setPolar(getMajorRadius(), angle); setRatio(p.getMagnitude() / getMajorRadius()); }