⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rs_arc.cpp

📁 qcad2.05可用于windows和linux的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************** $Id: rs_arc.cpp 2399 2005-06-06 18:12:30Z andrew $**** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.**** This file is part of the qcadlib Library project.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid qcadlib Professional Edition licenses may use ** this file in accordance with the qcadlib Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.ribbonsoft.com for further details.**** Contact info@ribbonsoft.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "rs_arc.h"#include "rs_constructionline.h"#include "rs_linetypepattern.h"#include "rs_information.h"#include "rs_math.h"#include "rs_graphicview.h"#include "rs_painter.h"/** * Default constructor. */RS_Arc::RS_Arc(RS_EntityContainer* parent,               const RS_ArcData& d)        : RS_AtomicEntity(parent), data(d) {    calculateEndpoints();    calculateBorders();}/** * Creates this arc from 3 given points which define the arc line. * * @param p1 1st point. * @param p2 2nd point. * @param p3 3rd point. */bool RS_Arc::createFrom3P(const RS_Vector& p1, const RS_Vector& p2,                          const RS_Vector& p3) {    if (p1.distanceTo(p2)>RS_TOLERANCE &&            p2.distanceTo(p3)>RS_TOLERANCE &&            p3.distanceTo(p1)>RS_TOLERANCE) {        // middle points between 3 points:        RS_Vector mp1, mp2;        RS_Vector dir1, dir2;        double a1, a2;        // intersection of two middle lines        mp1 = (p1 + p2)/2.0;        a1 = p1.angleTo(p2) + M_PI/2.0;        dir1.setPolar(100.0, a1);        mp2 = (p2 + p3)/2.0;        a2 = p2.angleTo(p3) + M_PI/2.0;        dir2.setPolar(100.0, a2);        RS_ConstructionLineData d1(mp1, mp1 + dir1);        RS_ConstructionLineData d2(mp2, mp2 + dir2);        RS_ConstructionLine midLine1(NULL, d1);        RS_ConstructionLine midLine2(NULL, d2);        RS_VectorSolutions sol =            RS_Information::getIntersection(&midLine1, &midLine2);        data.center = sol.get(0);        data.radius = data.center.distanceTo(p3);        data.angle1 = data.center.angleTo(p1);        data.angle2 = data.center.angleTo(p3);        data.reversed = RS_Math::isAngleBetween(data.center.angleTo(p2),                                                data.angle1, data.angle2, true);        if (sol.get(0).valid && data.radius<1.0e14 &&                data.radius>RS_TOLERANCE) {            calculateEndpoints();            calculateBorders();            return true;        } else {            RS_DEBUG->print("RS_Arc::createFrom3P(): "                            "Cannot create an arc with inf radius.");            return false;        }    } else {        RS_DEBUG->print("RS_Arc::createFrom3P(): "                        "Cannot create an arc with radius 0.0.");        return false;    }}/** * Creates an arc from its startpoint, endpoint, start direction (angle) * and radius. *  * @retval true Successfully created arc * @retval false Cannot creats arc (radius to small or endpoint to far away) */bool RS_Arc::createFrom2PDirectionRadius(const RS_Vector& startPoint,        const RS_Vector& endPoint,        double direction1, double radius) {    RS_Vector ortho;    ortho.setPolar(radius, direction1 + M_PI/2.0);    RS_Vector center1 = startPoint + ortho;    RS_Vector center2 = startPoint - ortho;    if (center1.distanceTo(endPoint) < center2.distanceTo(endPoint)) {        data.center = center1;    } else {        data.center = center2;    }    data.radius = radius;    data.angle1 = data.center.angleTo(startPoint);    data.angle2 = data.center.angleTo(endPoint);    data.reversed = false;    double diff = RS_Math::correctAngle(getDirection1()-direction1);    if (fabs(diff-M_PI)<1.0e-1) {        data.reversed = true;    }    calculateEndpoints();    calculateBorders();    return true;}/** * Creates an arc from its startpoint, endpoint and bulge. */bool RS_Arc::createFrom2PBulge(const RS_Vector& startPoint, const RS_Vector& endPoint,                               double bulge) {    data.reversed = (bulge<0.0);    double alpha = atan(bulge)*4.0;    RS_Vector middle = (startPoint+endPoint)/2.0;    double dist = startPoint.distanceTo(endPoint)/2.0;    // alpha can't be 0.0 at this point    data.radius = fabs(dist / sin(alpha/2.0));    double wu = fabs(RS_Math::pow(data.radius, 2.0) - RS_Math::pow(dist, 2.0));    double h = sqrt(wu);    double angle = startPoint.angleTo(endPoint);    if (bulge>0.0) {        angle+=M_PI/2.0;    } else {        angle-=M_PI/2.0;    }    if (fabs(alpha)>M_PI) {        h*=-1.0;    }    data.center.setPolar(h, angle);    data.center+=middle;    data.angle1 = data.center.angleTo(startPoint);    data.angle2 = data.center.angleTo(endPoint);    calculateEndpoints();    calculateBorders();	return true;}/** * Recalculates the endpoints using the angles and the radius. */void RS_Arc::calculateEndpoints() {    startpoint.set(data.center.x + cos(data.angle1) * data.radius,                   data.center.y + sin(data.angle1) * data.radius);    endpoint.set(data.center.x + cos(data.angle2) * data.radius,                 data.center.y + sin(data.angle2) * data.radius);}void RS_Arc::calculateBorders() {    double minX = std::min(startpoint.x, endpoint.x);    double minY = std::min(startpoint.y, endpoint.y);    double maxX = std::max(startpoint.x, endpoint.x);    double maxY = std::max(startpoint.y, endpoint.y);    double a1 = !isReversed() ? data.angle1 : data.angle2;    double a2 = !isReversed() ? data.angle2 : data.angle1;    // check for left limit:    if ((a1<M_PI && a2>M_PI) ||            (a1>a2-1.0e-12 && a2>M_PI) ||            (a1>a2-1.0e-12 && a1<M_PI) ) {        minX = std::min(data.center.x - data.radius, minX);    }    // check for right limit:    if (a1 > a2-1.0e-12) {        maxX = std::max(data.center.x + data.radius, maxX);    }    // check for bottom limit:    if ((a1<(M_PI_2*3) && a2>(M_PI_2*3)) ||            (a1>a2-1.0e-12    && a2>(M_PI_2*3)) ||            (a1>a2-1.0e-12    && a1<(M_PI_2*3)) ) {        minY = std::min(data.center.y - data.radius, minY);    }    // check for top limit:    if ((a1<M_PI_2 && a2>M_PI_2) ||            (a1>a2-1.0e-12   && a2>M_PI_2) ||            (a1>a2-1.0e-12   && a1<M_PI_2) ) {        maxY = std::max(data.center.y + data.radius, maxY);    }    minV.set(minX, minY);    maxV.set(maxX, maxY);}RS_VectorSolutions RS_Arc::getRefPoints() {    RS_VectorSolutions ret(startpoint, endpoint, data.center);    return ret;}RS_Vector RS_Arc::getNearestEndpoint(const RS_Vector& coord, double* dist) {    double dist1, dist2;    RS_Vector* nearerPoint;    dist1 = startpoint.distanceTo(coord);    dist2 = endpoint.distanceTo(coord);    if (dist2<dist1) {        if (dist!=NULL) {            *dist = dist2;        }        nearerPoint = &endpoint;    } else {        if (dist!=NULL) {            *dist = dist1;        }        nearerPoint = &startpoint;    }    return *nearerPoint;}RS_Vector RS_Arc::getNearestPointOnEntity(const RS_Vector& coord,        bool onEntity, double* dist, RS_Entity** entity) {    RS_Vector vec(false);    if (entity!=NULL) {        *entity = this;    }    double angle = (coord-data.center).angle();    if (onEntity==false || RS_Math::isAngleBetween(angle,            data.angle1, data.angle2, isReversed())) {        vec.setPolar(data.radius, angle);        vec+=data.center;    }    if (dist!=NULL) {        *dist = fabs((vec-data.center).magnitude()-data.radius);    }    return vec;}RS_Vector RS_Arc::getNearestCenter(const RS_Vector& coord,                                   double* dist) {    if (dist!=NULL) {        *dist = coord.distanceTo(data.center);    }    return data.center;}RS_Vector RS_Arc::getNearestMiddle(const RS_Vector& coord,                                   double* dist) {    RS_Vector ret = getMiddlepoint();    if (dist!=NULL) {        *dist = coord.distanceTo(ret);    }    return ret;}RS_Vector RS_Arc::getNearestDist(double distance,                                 const RS_Vector& coord,                                 double* dist) {    if (data.radius<1.0e-6) {        if (dist!=NULL) {            *dist = RS_MAXDOUBLE;        }        return RS_Vector(false);    }    double a1, a2;    RS_Vector p1, p2;    double aDist = distance / data.radius;    if (isReversed()) {        a1 = data.angle1 - aDist;        a2 = data.angle2 + aDist;    } else {        a1 = data.angle1 + aDist;        a2 = data.angle2 - aDist;    }    p1.setPolar(data.radius, a1);    p1 += data.center;    p2.setPolar(data.radius, a2);    p2 += data.center;    double dist1, dist2;    RS_Vector* nearerPoint;    dist1 = p1.distanceTo(coord);    dist2 = p2.distanceTo(coord);    if (dist2<dist1) {        if (dist!=NULL) {            *dist = dist2;        }        nearerPoint = &p2;    } else {        if (dist!=NULL) {            *dist = dist1;        }        nearerPoint = &p1;    }    return *nearerPoint;}RS_Vector RS_Arc::getNearestDist(double distance,                                 bool startp) {    if (data.radius<1.0e-6) {        return RS_Vector(false);    }    double a;    RS_Vector p;    double aDist = distance / data.radius;    if (isReversed()) {        if (startp) {            a = data.angle1 - aDist;        } else {            a = data.angle2 + aDist;        }    } else {        if (startp) {            a = data.angle1 + aDist;        } else {            a = data.angle2 - aDist;        }    }    p.setPolar(data.radius, a);    p += data.center;    return p;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -