bool MgArc::_setHandlePoint(int index, const Point2d& pt, float) { if (index == 1) { return setStartMidEnd(pt, getMidPoint(), getEndPoint()); } if (index == 2) { return setStartMidEnd(getStartPoint(), getMidPoint(), pt); } if (index == 3) { return setStartMidEnd(getStartPoint(), pt, getEndPoint()); } if (index == 4) { float a = (pt - getCenter()).angle2(); return setCenterRadius(getCenter(), getRadius(), a, getEndAngle() - a); } if (index == 5) { float a = (pt - getCenter()).angle2(); return setCenterRadius(getCenter(), getRadius(), getStartAngle(), a - getStartAngle()); } if (index == 6) { return setTanStartEnd(pt - getStartPoint(), getStartPoint(), getEndPoint()); } if (index == 7) { return (setTanStartEnd(getEndPoint() - pt, getEndPoint(), getStartPoint()) && _reverse()); } return setCenterStartEnd(pt, getStartPoint(), getEndPoint()); }
QList<RVector> RArc::getPointsWithDistanceToEnd(double distance, RS::From from) const { QList<RVector> ret; if (radius<RS::PointTolerance) { return ret; } double a1; double a2; RVector p; double aDist = distance / radius; if (isReversed()) { a1 = getStartAngle() - aDist; a2 = getEndAngle() + aDist; } else { a1 = getStartAngle() + aDist; a2 = getEndAngle() - aDist; } if (from==RS::FromStart || from==RS::FromAny) { p.setPolar(radius, a1); p += center; ret.append(p); } if (from==RS::FromEnd || from==RS::FromAny) { p.setPolar(radius, a2); p += center; ret.append(p); } return ret; }
void MgArc::_update() { Point2d points[16]; int n = mgAngleArcToBezier(points, getCenter(), getRadius(), 0, getStartAngle(), getSweepAngle()); mgBeziersBox(_extent, n, points); }
float MgArc::_hitTest(const Point2d& pt, float tol, MgHitResult& res) const { Point2d points[16]; int n = mgcurv::arcToBezier(points, getCenter(), getRadius(), 0, getStartAngle(), getSweepAngle()); float dist, distMin = _FLT_MAX; Point2d ptTemp; if (_subtype > 0) { dist = mglnrel::ptToLine(getCenter(), getStartPoint(), pt, ptTemp); if (dist <= tol && dist < distMin) { distMin = dist; res.nearpt = ptTemp; } dist = mglnrel::ptToLine(getCenter(), getEndPoint(), pt, ptTemp); if (dist <= tol && dist < distMin) { distMin = dist; res.nearpt = ptTemp; } } for (int i = 0; i + 3 < n; i += 3) { mgnear::nearestOnBezier(pt, points + i, ptTemp); dist = pt.distanceTo(ptTemp); if (dist <= tol && dist < distMin) { distMin = dist; res.nearpt = ptTemp; } } return distMin; }
void Arc::draw(MyWindow* win) const { for(int r = getRadius(); r > endRadius; r--) { for(float theta = getStartAngle(); theta <= getEndAngle(); theta += 0.001) { win->putPixel(getCenter().getX() + r*cos(theta), getCenter().getY() + r*(-sin(theta)), getColor().r, getColor().g, getColor().b); //setPixel(discContainer, (center.getX() + r*cos(theta)), (center.getY() + r*(-sin(theta))), color); } } }
void RArcEntity::print(QDebug dbg) const { dbg.nospace() << "RArcEntity("; REntity::print(dbg); dbg.nospace() << ", center: " << getCenter(); dbg.nospace() << ", radius: " << getRadius(); dbg.nospace() << ", startAngle: " << RMath::rad2deg(getStartAngle()); dbg.nospace() << ", endAngle: " << RMath::rad2deg(getEndAngle()); dbg.nospace() << ", reversed: " << isReversed() << ")"; }
float MgArc::getSweepAngle() const { if (!mgIsZero(_sweepAngle)) { return _sweepAngle; } const float midAngle = (getMidPoint() - getCenter()).angle2(); const float startAngle = getStartAngle(); const float endAngle = getEndAngle(); if (mgEquals(midAngle, startAngle) && mgEquals(startAngle, endAngle)) { return endAngle - startAngle; } Tol tol(getRadius() * 1e-3f, 1e-4f); if (getStartPoint().isEqualTo(getEndPoint(), tol) && (getMidPoint() + (getStartPoint() + getEndPoint()) / 2).isEqualTo(2 * getCenter(), tol)) { return _M_2PI; } float startAngle2 = startAngle; float midAngle2 = midAngle; float endAngle2 = endAngle; // 先尝试看是否为逆时针方向:endAngle2 > midAngle2 > startAngle2 >= 0 if (startAngle2 < 0) startAngle2 += _M_2PI; while (midAngle2 < startAngle2) midAngle2 += _M_2PI; while (endAngle2 < midAngle2) endAngle2 += _M_2PI; if (fabsf(startAngle2 + endAngle2 - 2 * midAngle2) < _M_PI_6 && endAngle2 - startAngle2 < _M_2PI) { return endAngle2 - startAngle2; } // 再尝试看是否为顺时针方向:endAngle2 < midAngle2 < startAngle2 <= 0 startAngle2 = startAngle; midAngle2 = midAngle; endAngle2 = endAngle; if (startAngle2 > 0) startAngle2 -= _M_2PI; while (midAngle2 > startAngle2) midAngle2 -= _M_2PI; while (endAngle2 > midAngle2) endAngle2 -= _M_2PI; if (fabsf(startAngle2 + endAngle2 - 2 * midAngle2) < _M_PI_6) { if (endAngle2 - startAngle2 > -_M_2PI) return endAngle2 - startAngle2; return mgbase::toRange(endAngle2 - startAngle2, -_M_2PI, 0); } return endAngle - startAngle; // error }
bool MgArc::_hitTestBox(const Box2d& rect) const { if (!getExtent().isIntersect(rect)) return false; Point2d points[16]; int n = mgAngleArcToBezier(points, getCenter(), getRadius(), 0, getStartAngle(), getSweepAngle()); return mgBeziersIntersectBox(rect, n, points); }
double RArc::getDistanceFromStart(const RVector& p) const { double a1 = getStartAngle(); double ap = center.getAngleTo(p); if (reversed) { return RMath::getAngleDifference(ap, a1) * radius; } else { return RMath::getAngleDifference(a1, ap) * radius; } }
bool MgArc::_hitTestBox(const Box2d& rect) const { if (!getExtent().isIntersect(rect)) return false; Point2d points[16]; int n = mgcurv::arcToBezier(points, getCenter(), getRadius(), 0, getStartAngle(), getSweepAngle()); return rect.contains(getCenter()) || mgnear::beziersIntersectBox(rect, n, points); }
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() << ")"; }
void MgArc::_update() { Point2d points[16]; int n = mgcurv::arcToBezier(points, getCenter(), getRadius(), 0, getStartAngle(), getSweepAngle()); mgnear::beziersBox(_extent, n, points); if (_subtype > 0) { _extent.unionWith(getCenter()); } __super::_update(); }
bool MgArc::_draw(int mode, GiGraphics& gs, const GiContext& ctx, int segment) const { bool ret = gs.drawArc(&ctx, getCenter(), getRadius(), 0, getStartAngle(), getSweepAngle()); if (mode > 0) { GiContext ctxln(0, GiColor(0, 126, 0, 64), kGiLineDashDot); gs.drawLine(&ctxln, getCenter(), getStartPoint()); gs.drawLine(&ctxln, getCenter(), getEndPoint()); gs.drawLine(&ctxln, getStartPoint(), getStartPoint() + getStartTangent()); gs.drawLine(&ctxln, getEndPoint(), getEndPoint() + getEndTangent()); } return __super::_draw(mode, gs, ctx, segment) || ret; }
void RArc::print(QDebug dbg) const { dbg.nospace() << "RArc("; RShape::print(dbg); dbg.nospace() << ", center: " << getCenter() << ", radius: " << getRadius() << ", startAngle: " << getStartAngle() << ", endAngle: " << getEndAngle() << ", startPoint: " << getStartPoint() << ", endPoint: " << getEndPoint() << ", reversed: " << isReversed() << ")"; }
// Draw function void OcclusionArc::drawFunc() { BEGIN_DLIST GLUquadricObj* qobj = gluNewQuadric(); if (isFilled()) { gluQuadricDrawStyle(qobj, GLU_FILL); } else { gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); } gluPartialDisk(qobj, getRadius(), outerRadius, getSlices(), 2, getStartAngle(), getArcLength()); gluDeleteQuadric(qobj); END_DLIST }
float MgArc::getSweepAngle() const { const float midAngle = (getMidPoint() - getCenter()).angle2(); const float startAngle = getStartAngle(); const float endAngle = getEndAngle(); if (mgEquals(midAngle, startAngle) && mgEquals(startAngle, endAngle)) { return endAngle - startAngle; } float startAngle2 = startAngle; float midAngle2 = midAngle; float endAngle2 = endAngle; // 先尝试看是否为逆时针方向:endAngle2 > midAngle2 > startAngle2 >= 0 if (startAngle2 < 0) startAngle2 += _M_2PI; while (midAngle2 < startAngle2) midAngle2 += _M_2PI; while (endAngle2 < midAngle2) endAngle2 += _M_2PI; if (fabsf(startAngle2 + endAngle2 - 2 * midAngle2) < _M_PI_6 && endAngle2 - startAngle2 < _M_2PI) { return endAngle2 - startAngle2; } // 再尝试看是否为顺时针方向:endAngle2 < midAngle2 < startAngle2 <= 0 startAngle2 = startAngle; midAngle2 = midAngle; endAngle2 = endAngle; if (startAngle2 > 0) startAngle2 -= _M_2PI; while (midAngle2 > startAngle2) midAngle2 -= _M_2PI; while (endAngle2 > midAngle2) endAngle2 -= _M_2PI; if (fabsf(startAngle2 + endAngle2 - 2 * midAngle2) < _M_PI_6) { if (endAngle2 - startAngle2 > -_M_2PI) return endAngle2 - startAngle2; return mgToRange(endAngle2 - startAngle2, -_M_2PI, 0); } return endAngle - startAngle; // error }
float MgArc::_hitTest(const Point2d& pt, float tol, Point2d& nearpt, int&) const { Point2d points[16]; int n = mgAngleArcToBezier(points, getCenter(), getRadius(), 0, getStartAngle(), getSweepAngle()); float distMin = _FLT_MAX; Point2d ptTemp; for (int i = 0; i + 3 < n; i += 3) { mgNearestOnBezier(pt, points + i, ptTemp); float dist = pt.distanceTo(ptTemp); if (dist <= tol && dist < distMin) { distMin = dist; nearpt = ptTemp; } } return distMin; }
void MgArc::_output(MgPath& path) const { float r = getRadius(); float sweepAngle = getSweepAngle(); Point2d points[16]; if (r < _MGZERO || fabsf(sweepAngle) < _MGZERO) return; int count = mgcurv::arcToBezier(points, getCenter(), r, r, getStartAngle(), sweepAngle); if (_subtype > 0) { path.moveTo(getCenter()); path.lineTo(points[0]); path.beziersTo(count - 1, points + 1); path.closeFigure(); } else { path.moveTo(points[0]); path.beziersTo(count - 1, points + 1); } }
RPolyline RArc::approximateWithLines(double segmentLength) { RPolyline polyline; // avoid a segment length of 0: if (segmentLength<1.0e-6) { segmentLength = 1.0e-6; } double a1 = getStartAngle(); double a2 = getEndAngle(); double aStep = segmentLength / radius; double a, cix, ciy; polyline.appendVertex(getStartPoint()); if (!reversed) { // Arc Counterclockwise: if (a1>a2-1.0e-10) { a2+=2*M_PI; } for (a=a1+aStep; a<=a2; a+=aStep) { cix = center.x + cos(a) * radius; ciy = center.y + sin(a) * radius; polyline.appendVertex(RVector(cix, ciy)); } } else { // Arc Clockwise: if (a1<a2+1.0e-10) { a2-=2*M_PI; } for (a=a1-aStep; a>=a2; a-=aStep) { cix = center.x + cos(a) * radius; ciy = center.y + sin(a) * radius; polyline.appendVertex(RVector(cix, ciy)); } } polyline.appendVertex(getEndPoint()); return polyline; }
bool MgArc::_setHandlePoint2(int index, const Point2d& pt, float, int& data) { static float lastSweepAngle; if (index == 1 || index == 2) { // 起点、终点 return setCenterRadius(getCenter(), pt.distanceTo(getCenter()), getStartAngle(), getSweepAngle()); } if (index == 3) { // 弧线中点 return setStartMidEnd(getStartPoint(), pt, getEndPoint()); } if (index == 4) { // 改变起始角度 if (data == 0) { lastSweepAngle = getSweepAngle(); data++; } Point2d startPt(getCenter().polarPoint((pt - getCenter()).angle2(), getRadius())); bool ret = setCSE(getCenter(), startPt, getEndPoint(), lastSweepAngle); lastSweepAngle = getSweepAngle(); return ret; } if (index == 5) { // 改变终止角度 if (data == 0) { lastSweepAngle = getSweepAngle(); data++; } Point2d endPt(getCenter().polarPoint((pt - getCenter()).angle2(), getRadius())); bool ret = setCSE(getCenter(), getStartPoint(), endPt, lastSweepAngle); lastSweepAngle = getSweepAngle(); return ret; } if (index == 6) { return setTanStartEnd(pt - getStartPoint(), getStartPoint(), getEndPoint()); } if (index == 7) { return (setTanStartEnd(getEndPoint() - pt, getEndPoint(), getStartPoint()) && _reverse()); } return offset(pt - getCenter(), -1); }
//------------------------------------------------------------------------------ // drawFunc() -- draws the object(s) //------------------------------------------------------------------------------ void DialArcSegment::drawFunc() { // get our data from our base class double startAngle = getStartAngle(); double radius = getRadius(); double sweepAngle = getSweepAngle(); GLint curSlices = getSlices(); // our slice amount should go up as we get more of a sweep, if not, it will // look funny. Pretty much one slice per degree sweep double y = std::fabs(static_cast<double>(sweepAngle)); curSlices = curSlices + static_cast<GLint>(y * 0.05f); // draw our arc glPushMatrix(); GLUquadric* qobj = gluNewQuadric(); if (filled) gluQuadricDrawStyle(qobj, GL_FILL); else gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); gluPartialDisk(qobj, radius, outerRadius, curSlices, 1, startAngle, sweepAngle); gluDeleteQuadric(qobj); glPopMatrix(); }
//------------------------------------------------------------------------------ // drawFunc() -- draws the object(s) //------------------------------------------------------------------------------ void DialTickMarks::drawFunc() { GLfloat currentColor[4]; glGetFloatv(GL_CURRENT_COLOR, currentColor); // get our data from our baseclass (AnalogDial) double sweepAngle = getSweepAngle(); double startAngle = getStartAngle(); double tRadius = getRadius(); // figure our rotation angle per tick mark (deg) double rotation = sweepAngle/quantity; glPushMatrix(); // rotate to our start angle glRotatef(static_cast<GLfloat>(-startAngle), 0, 0, 1); for (int i = 0; i < quantity + 1; i++) { // if we have a graphic, draw that, else we draw a line if (myGraphic == nullptr) { glBegin(GL_LINES); lcVertex2(0, tRadius); lcVertex2(0, tRadius - length); glEnd(); } else { myGraphic->lcSaveMatrix(); myGraphic->lcTranslate(0, tRadius); myGraphic->draw(); myGraphic->lcRestoreMatrix(); } glRotatef(static_cast<GLfloat>(-rotation), 0, 0, 1); } glPopMatrix(); glColor4fv(currentColor); }