void REllipseEntity::print(QDebug dbg) const { dbg.nospace() << "REllipseEntity("; REntity::print(dbg); dbg.nospace() << ", center: " << getCenter(); dbg.nospace() << ", majorPoint: " << getMajorPoint(); dbg.nospace() << ", ratio: " << getRatio(); dbg.nospace() << ", startAngle: " << getStartAngle(); dbg.nospace() << ", endAngle: " << getEndAngle(); dbg.nospace() << ", reversed: " << isReversed() << ")"; }
bool REllipse::switchMajorMinor() { if (fabs(ratio) < RS::PointTolerance) { return false; } RVector vp_start=getStartPoint(); RVector vp_end=getStartPoint(); RVector vp=getMajorPoint(); setMajorPoint(RVector(-ratio*vp.y, ratio*vp.x)); setRatio(1.0/ratio); setStartParam(getParamTo(vp_start)); setEndParam(getParamTo(vp_end)); return true; }
void REllipse::print(QDebug dbg) const { dbg.nospace() << "REllipse("; RShape::print(dbg); dbg.nospace() << ", startPoint: " << getStartPoint() << ", endPoint: " << getEndPoint() << ", center: " << getCenter() << ", majorPoint: " << getMajorPoint() << ", majorRadius: " << getMajorRadius() << ", minorRadius: " << getMinorRadius() << ", ratio: " << getRatio() << ", startAngle: " << RMath::rad2deg(getStartParam()) << ", endAngle: " << RMath::rad2deg(getEndParam()) << ", full: " << isFullEllipse() << ", clockwise: " << isReversed() << ")"; }
QSharedPointer<RShape> REllipse::getTransformed(const QTransform& transform) const { RVector ct = center.getTransformed2d(transform); RVector mp = center + getMajorPoint(); RVector mpt = mp.getTransformed2d(transform); RVector sp = getStartPoint(); RVector spt = sp.getTransformed2d(transform); RVector ep = getEndPoint(); RVector ept = ep.getTransformed2d(transform); QSharedPointer<REllipse> ret = QSharedPointer<REllipse>( new REllipse( ct, mpt - ct, ratio, 0.0, M_PI*2, reversed ) ); ret->setStartParam(ret->getParamTo(spt)); ret->setEndParam(ret->getParamTo(ept)); return ret; }
QList<RLine> REllipse::getTangents(const RVector& point) const { QList<RLine> ret; if (getDistanceTo(point, false) < RS::PointTolerance) { // point is on ellipse: return ret; } // point is at center (prevents recursion when swapping ellipse minor / major): if (point.getDistanceTo(getCenter())<RS::PointTolerance) { return ret; } // swap ellipse minor / major if point is on minor axis // 20120928: and not also on major axis (prevent recursion): RLine minorAxis(getCenter(), getCenter() + getMinorPoint()); RLine majorAxis(getCenter(), getCenter() + getMajorPoint()); if (minorAxis.isOnShape(point, false) && !majorAxis.isOnShape(point, false)) { REllipse e2 =*this; e2.majorPoint = getMinorPoint(); e2.ratio = 1.0/ratio; return e2.getTangents(point); } double a = getMajorRadius(); // the length of the major axis / 2 double b = getMinorRadius(); // the length of the minor axis / 2 // rotate and move point: RVector point2 = point; point2.move(-getCenter()); point2.rotate(-getAngle()); double xp = point2.x; // coordinates of the given point double yp = point2.y; double xt1; // Tangent point 1 double yt1; double xt2; // Tangent point 2 double yt2; double a2 = a * a; double b2 = b * b; double d = a2 / b2 * yp / xp; double e = a2 / xp; double af = b2 * d * d + a2; double bf = -b2 * d * e * 2.0; double cf = b2 * e * e - a2 * b2; double t = sqrt(bf * bf - af * cf * 4.0); if (RMath::isNaN(t)) { return ret; } yt1 = (t - bf) / (af * 2.0); xt1 = e - d * yt1; yt2 = (-t - bf) / (af * 2.0); xt2 = e - d * yt2; RVector s1(xt1, yt1); s1.rotate(getAngle()); s1.move(getCenter()); RVector s2(xt2, yt2); s2.rotate(getAngle()); s2.move(getCenter()); if (s1.isValid()) { ret.append(RLine(point, s1)); } if (s2.isValid()) { ret.append(RLine(point, s2)); } return ret; }
QList<RVector> REllipse::getFoci() const { RVector vp(getMajorPoint() * sqrt(1.0 - getRatio()*getRatio())); return QList<RVector>() << getCenter()+vp << getCenter()-vp; }