Ejemplo n.º 1
0
RS_Vector RS_Image::getNearestPointOnEntity(const RS_Vector& coord,
        bool onEntity, double* dist, RS_Entity** entity) const{

    if (entity!=NULL) {
        *entity = const_cast<RS_Image*>(this);
    }

    RS_VectorSolutions corners =getCorners();
    //allow selecting image by clicking within images, bug#3464626
    if(containsPoint(coord)){
        //if coord is within image
        if(dist!=NULL) *dist=0.;
        return coord;
    }
    RS_VectorSolutions points(4);

    RS_Line l[] =
        {
            RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
            RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
            RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
            RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
        };

    for (int i=0; i<4; ++i) {
        points.set(i, l[i].getNearestPointOnEntity(coord, onEntity));
    }

    return points.getClosest(coord, dist);
}
Ejemplo n.º 2
0
/**
//create Ellipse with axes in x-/y- directions from 4 points
*
*
*@Author Dongxu Li
*/
bool	RS_Ellipse::createFrom4P(const RS_VectorSolutions& sol)
{
    if (sol.getNumber() != 4 ) return (false); //only do 4 points
    QVector<QVector<double> > mt;
    QVector<double> dn;
    int mSize(4);
    mt.resize(mSize);
    for(int i=0;i<mSize;i++) {//form the linear equation, c0 x^2 + c1 x + c2 y^2 + c3 y = 1
        mt[i].resize(mSize+1);
        mt[i][0]=sol.get(i).x * sol.get(i).x;
        mt[i][1]=sol.get(i).x ;
        mt[i][2]=sol.get(i).y * sol.get(i).y;
        mt[i][3]=sol.get(i).y ;
        mt[i][4]=1.;
    }
    if ( ! RS_Math::linearSolver(mt,dn)) return false;
    double d(1.+0.25*(dn[1]*dn[1]/dn[0]+dn[3]*dn[3]/dn[2]));
    if(fabs(dn[0])<RS_TOLERANCE*RS_TOLERANCE
            ||fabs(dn[2])<RS_TOLERANCE*RS_TOLERANCE
            ||d/dn[0]<RS_TOLERANCE*RS_TOLERANCE
            ||d/dn[2]<RS_TOLERANCE*RS_TOLERANCE
            ) {
        //ellipse not defined
        return false;
    }
    data.center.set(-0.5*dn[1]/dn[0],-0.5*dn[3]/dn[2]); // center
    d=sqrt(d/dn[0]);
    data.majorP.set(d,0.);
    data.ratio=sqrt(dn[0]/dn[2]);
    data.angle1=0.;
    data.angle2=0.;
    return true;

}
Ejemplo n.º 3
0
void RS_Image::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) {
	if (!(painter && view) || !img.get() || img->isNull())
		return;

    // erase image:
    //if (painter->getPen().getColor()==view->getBackground()) {
    //	RS_VectorSolutions sol = getCorners();
    //
    //}

	RS_Vector scale{view->toGuiDX(data.uVector.magnitude()),
								view->toGuiDY(data.vVector.magnitude())};
    double angle = data.uVector.angle();

	painter->drawImg(*img,
                     view->toGui(data.insertionPoint),
                     angle, scale);

    if (isSelected()) {
        RS_VectorSolutions sol = getCorners();
		for (size_t i = 0; i < sol.size(); ++i){
			size_t const j = (i+1)%sol.size();
			painter->drawLine(view->toGui(sol.get(i)), view->toGui(sol.get(j)));
		}
    }
}
Ejemplo n.º 4
0
double RS_Image::getDistanceToPoint(const RS_Vector& coord,
                                    RS_Entity** entity,
                                    RS2::ResolveLevel /*level*/,
                                                                        double /*solidDist*/) const{
    if (entity) {
        *entity = const_cast<RS_Image*>(this);
    }

    RS_VectorSolutions corners = getCorners();

    //allow selecting image by clicking within images, bug#3464626
	if(containsPoint(coord)){
		//if coord is on image

		RS_SETTINGS->beginGroup("/Appearance");
		bool draftMode = (bool)RS_SETTINGS->readNumEntry("/DraftMode", 0);
		RS_SETTINGS->endGroup();
		if(!draftMode) return double(0.);
	}
    //continue to allow selecting by image edges
    double minDist = RS_MAXDOUBLE;

	for (size_t i = 0; i < corners.size(); ++i){
		size_t const j = (i+1)%corners.size();
		RS_Line const l{corners.get(i), corners.get(j)};
		double const dist = l.getDistanceToPoint(coord, nullptr);
		minDist = std::min(minDist, dist);
	}

    return minDist;
}
Ejemplo n.º 5
0
void RS_Image::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) {
	if (painter==NULL || view==NULL || !img.get() || img->isNull()) {
        return;
    }

    // erase image:
    //if (painter->getPen().getColor()==view->getBackground()) {
    //	RS_VectorSolutions sol = getCorners();
    //
    //}

    RS_Vector scale = RS_Vector(view->toGuiDX(data.uVector.magnitude()),
                                view->toGuiDY(data.vVector.magnitude()));
    double angle = data.uVector.angle();

	painter->drawImg(*img,
                     view->toGui(data.insertionPoint),
                     angle, scale);

    if (isSelected()) {
        RS_VectorSolutions sol = getCorners();

        painter->drawLine(view->toGui(sol.get(0)), view->toGui(sol.get(1)));
        painter->drawLine(view->toGui(sol.get(1)), view->toGui(sol.get(2)));
        painter->drawLine(view->toGui(sol.get(2)), view->toGui(sol.get(3)));
        painter->drawLine(view->toGui(sol.get(3)), view->toGui(sol.get(0)));
    }
}
Ejemplo n.º 6
0
void RS_Image::calculateBorders() {

    RS_VectorSolutions sol = getCorners();
        minV =  RS_Vector::minimum(
                RS_Vector::minimum(sol.get(0), sol.get(1)),
                RS_Vector::minimum(sol.get(2), sol.get(3))
                    );
        maxV =  RS_Vector::maximum(
                RS_Vector::maximum(sol.get(0), sol.get(1)),
                RS_Vector::maximum(sol.get(2), sol.get(3))
                    );
}
/**
 * Helper function for makeContour
 * Calculate the intersection point of first and last entities
 * The first vertex is not added and the last is returned instead of added
 *
 * @retval RS_Vector nearest to startpoint of last and endpoint of first or RS_Vector(false) if not
 *
 * @author Rallaz
 */
RS_Vector RS_ActionPolylineEquidistant::calculateIntersection(RS_Entity* first,RS_Entity* last) {
    RS_VectorSolutions vsol;
    RS_Vector v(false);
    vsol = RS_Information::getIntersection(first, last, false);
    if (vsol.getNumber()==0) {
        //Parallel entities
        return RS_Vector(false);
    } else if (vsol.getNumber()>1 &&
               vsol.get(0).distanceTo(last->getStartpoint()) > vsol.get(1).distanceTo(last->getStartpoint())) {
        return vsol.get(1);
    }
    return vsol.get(0);
}
Ejemplo n.º 8
0
/**
 * 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;
    }
}
Ejemplo n.º 9
0
RS_Vector RS_Line::prepareTrim(const RS_Vector& trimCoord,
                               const RS_VectorSolutions& trimSol) {
//prepare trimming for multiple intersections
    if ( ! trimSol.hasValid()) return(RS_Vector(false));
    if ( trimSol.getNumber() == 1 ) return(trimSol.get(0));
    auto&& vp0=trimSol.getClosest(trimCoord,NULL,0);

    double dr2=trimCoord.squaredTo(vp0);
    //the trim point found is closer to mouse location (trimCoord) than both end points, return this trim point
    if(dr2 < trimCoord.squaredTo(getStartpoint()) && dr2 < trimCoord.squaredTo(getEndpoint())) return vp0;
    //the closer endpoint to trimCoord
    RS_Vector vp1=(trimCoord.squaredTo(getStartpoint()) <= trimCoord.squaredTo(getEndpoint()))?getStartpoint():getEndpoint();

    //searching for intersection in the direction of the closer end point
    auto&& dvp1=vp1 - trimCoord;
    RS_VectorSolutions sol1;
    for(size_t i=0; i<trimSol.size(); i++){
        auto&& dvp2=trimSol.at(i) - trimCoord;
        if( RS_Vector::dotP(dvp1, dvp2) > RS_TOLERANCE) sol1.push_back(trimSol.at(i));
    }
    //if found intersection in direction, return the closest to trimCoord from it
    if(sol1.size()) return sol1.getClosest(trimCoord,NULL,0);

    //no intersection by direction, return previously found closest intersection
    return vp0;
}
void RS_ActionInfoAngle::trigger() {

    RS_DEBUG->print("RS_ActionInfoAngle::trigger()");

    if (entity1!=NULL && entity2!=NULL) {
        RS_VectorSolutions sol =
            RS_Information::getIntersection(entity1, entity2, false);

        if (sol.hasValid()) {
            intersection = sol.get(0);

            if (intersection.valid && point1.valid && point2.valid) {
                double angle1 = intersection.angleTo(point1);
                double angle2 = intersection.angleTo(point2);
                double angle = RS_Math::rad2deg(remainder(angle2-angle1,2.*M_PI));

                QString str;
                str.setNum(angle);
                str += QChar(0xB0);
                if(angle<0.) {
                    QString str2;
                    str2.setNum(angle+360.); //positive value
                    str += QString(" or %1%2").arg(str2).arg(QChar(0xB0));
                }
                RS_DIALOGFACTORY->commandMessage(tr("Angle: %1").arg(str));
            }
        } else {
            RS_DIALOGFACTORY->commandMessage(tr("Lines are parallel"));
        }
    }
}
Ejemplo n.º 11
0
/**
 * @return One or two intersection points between given entities.
 */
RS_VectorSolutions RS_Information::getIntersectionEllipseLine(RS_Line* line,
        RS_Ellipse* ellipse) {

    RS_VectorSolutions ret;

    if (line==NULL || ellipse==NULL) {
        return ret;
    }

    // rotate into normal position:

    double rx = ellipse->getMajorRadius();
    if(rx<RS_TOLERANCE) {
        //zero radius ellipse
        RS_Vector vp(line->getNearestPointOnEntity(ellipse->getCenter(), true));
        if((vp-ellipse->getCenter()).squared() <RS_TOLERANCE2){
            //center on line
            ret.push_back(vp);
        }
        return ret;
    }
    RS_Vector angleVector = ellipse->getMajorP().scale(RS_Vector(1./rx,-1./rx));
    double ry = rx*ellipse->getRatio();
    RS_Vector center = ellipse->getCenter();
    RS_Vector a1 = line->getStartpoint().rotate(center, angleVector);
    RS_Vector a2 = line->getEndpoint().rotate(center, angleVector);
//    RS_Vector origin = a1;
    RS_Vector dir = a2-a1;
    RS_Vector diff = a1 - center;
    RS_Vector mDir = RS_Vector(dir.x/(rx*rx), dir.y/(ry*ry));
    RS_Vector mDiff = RS_Vector(diff.x/(rx*rx), diff.y/(ry*ry));

    double a = RS_Vector::dotP(dir, mDir);
    double b = RS_Vector::dotP(dir, mDiff);
    double c = RS_Vector::dotP(diff, mDiff) - 1.0;
    double d = b*b - a*c;

//    std::cout<<"RS_Information::getIntersectionEllipseLine(): d="<<d<<std::endl;
    if (d < - 1.e3*RS_TOLERANCE*sqrt(RS_TOLERANCE)) {
        RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 0");
        return ret;
    }
    if( d < 0. ) d=0.;
    double root = sqrt(d);
    double t_a = -b/a;
    double t_b = root/a;
    //        double t_b = (-b + root) / a;

    ret.push_back(a1.lerp(a2,t_a+t_b));
    RS_Vector vp(a1.lerp(a2,t_a-t_b));
    if ( (ret.get(0)-vp).squared()>RS_TOLERANCE2) {
        ret.push_back(vp);
    }
    angleVector.y *= -1.;
    ret.rotate(center, angleVector);
//    std::cout<<"found Ellipse-Line intersections: "<<ret.getNumber()<<std::endl;
//    std::cout<<ret<<std::endl;
    RS_DEBUG->print("RS_Information::getIntersectionEllipseLine(): done");
    return ret;
}
Ejemplo n.º 12
0
RS_Vector RS_Line::prepareTrim(const RS_Vector& trimCoord,
                               const RS_VectorSolutions& trimSol) {
//prepare trimming for multiple intersections
    if ( ! trimSol.hasValid()) return(RS_Vector(false));
    if ( trimSol.getNumber() == 1 ) return(trimSol.get(0));
    return trimSol.getClosest(trimCoord,NULL,0);
}
Ejemplo n.º 13
0
void RS_ActionInfoAngle::trigger() {

    RS_DEBUG->print("RS_ActionInfoAngle::trigger()");

    if (entity1 && entity2) {
        RS_VectorSolutions sol =
            RS_Information::getIntersection(entity1, entity2, false);

        if (sol.hasValid()) {
            intersection = sol.get(0);

            if (intersection.valid && point1.valid && point2.valid) {
                double angle1 = intersection.angleTo(point1);
                double angle2 = intersection.angleTo(point2);
				double angle = remainder(angle2-angle1,2.*M_PI);

				QString str = RS_Units::formatAngle(angle,
													graphic->getAngleFormat(), graphic->getAnglePrecision());

                if(angle<0.){
					str += " or ";
					str += RS_Units::formatAngle(angle + 2.*M_PI,
												 graphic->getAngleFormat(), graphic->getAnglePrecision());
                }
                RS_DIALOGFACTORY->commandMessage(tr("Angle: %1").arg(str));
            }
        } else {
            RS_DIALOGFACTORY->commandMessage(tr("Lines are parallel"));
        }
    }
}
Ejemplo n.º 14
0
void RS_ActionInfoAngle::trigger() {

    RS_DEBUG->print("RS_ActionInfoAngle::trigger()");

    if (entity1!=NULL && entity2!=NULL) {
        RS_VectorSolutions sol =
            RS_Information::getIntersection(entity1, entity2, false);

        if (sol.hasValid()) {
            intersection = sol.get(0);

            if (intersection.valid && point1.valid && point2.valid) {
                double angle1 = intersection.angleTo(point1);
                double angle2 = intersection.angleTo(point2);
                double angle = fabs(angle2-angle1);

                QString str;
                str.sprintf("%.6f", RS_Math::rad2deg(angle));
                RS_DIALOGFACTORY->commandMessage(tr("Angle: %1%2")
                                                 .arg(str).arg(QChar(0xB0)));
            }
        } else {
            RS_DIALOGFACTORY->commandMessage(tr("Lines are parallel"));
        }
    }
}
Ejemplo n.º 15
0
/**
 * @return Center of the measured dimension.
 */
RS_Vector RS_DimAngular::getCenter() {
    RS_ConstructionLine l1(NULL, RS_ConstructionLineData(edata.definitionPoint1,
                           edata.definitionPoint2));
    RS_ConstructionLine l2(NULL, RS_ConstructionLineData(edata.definitionPoint3,
                           data.definitionPoint));
    RS_VectorSolutions vs = RS_Information::getIntersection(&l1, &l2, false);

    return vs.get(0);
}
Ejemplo n.º 16
0
/**
 * Creates a bisecting line of the angle between the entities
 * e1 and e2. Out of the 4 possible bisectors, the one closest to
 * the given coordinate is returned.
 *
 * @param coord Coordinate to define which bisector we want (typically a
 *              mouse coordinate).
 * @param length Length of the bisecting line.
 * @param num Number of bisectors
 * @param l1 First line.
 * @param l2 Second line.
 *
 * @return Pointer to the first bisector created or nullptr if no bisectors
 *   were created.
 */
RS_Line* RS_Creation::createBisector(const RS_Vector& coord1,
                                     const RS_Vector& coord2,
                                     double length,
                                     int num,
                                     RS_Line* l1,
                                     RS_Line* l2) {

    RS_VectorSolutions sol;
    // check given entities:
	if( ! (l1 && l2)) return nullptr;
	if(! (l1->rtti()==RS2::EntityLine && l1->rtti()==RS2::EntityLine)) return nullptr;

    // intersection between entities:
    sol = RS_Information::getIntersection(l1, l2, false);
    RS_Vector inters = sol.get(0);
    if (inters.valid==false) {
		return nullptr;
    }

    double angle1 = inters.angleTo(l1->getNearestPointOnEntity(coord1));
    double angle2 = inters.angleTo(l2->getNearestPointOnEntity(coord2));
    double angleDiff = RS_Math::getAngleDifference(angle1, angle2);
    if (angleDiff>M_PI) {
		angleDiff = angleDiff - 2.*M_PI;
    }
	RS_Line* ret = nullptr;

	if (document && handleUndo) {
        document->startUndoCycle();
    }

    for (int n=1; n<=num; ++n) {

        double angle = angle1 +
                (angleDiff / (num+1) * n);

        RS_LineData d;
        RS_Vector v;

        v.setPolar(length, angle);
        d = RS_LineData(inters, inters + v);

        RS_Line* newLine = new RS_Line(container, d);
		if (ret==nullptr) {
			ret = newLine;
		}
		setEntity(newLine);
    }
	if (document && handleUndo) {
        document->endUndoCycle();
    }

    return ret;
}
Ejemplo n.º 17
0
RS_Vector RS_Image::getNearestDist(double distance,
                                   const RS_Vector& coord,
                                   double* dist) {

    RS_VectorSolutions corners = getCorners();
    RS_VectorSolutions points(4);

    RS_Line l[] =
        {
            RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
            RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
            RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
            RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
        };

    for (int i=0; i<4; ++i) {
        points.set(i, l[i].getNearestDist(distance, coord, dist));
    }

    return points.getClosest(coord, dist);
}
Ejemplo n.º 18
0
double RS_Image::getDistanceToPoint(const RS_Vector& coord,
                                    RS_Entity** entity,
                                    RS2::ResolveLevel /*level*/,
                                                                        double /*solidDist*/) const{
    if (entity!=NULL) {
        *entity = const_cast<RS_Image*>(this);
    }

    RS_VectorSolutions corners = getCorners();

    //allow selecting image by clicking within images, bug#3464626
	if(containsPoint(coord)){
		//if coord is on image

		RS_SETTINGS->beginGroup("/Appearance");
		bool draftMode = (bool)RS_SETTINGS->readNumEntry("/DraftMode", 0);
		RS_SETTINGS->endGroup();
		if(!draftMode) return double(0.);
	}
    //continue to allow selecting by image edges
    double dist;
    double minDist = RS_MAXDOUBLE;

    RS_Line l[] =
        {
            RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
            RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
            RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
            RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
        };

    for (int i=0; i<4; ++i) {
        dist = l[i].getDistanceToPoint(coord, NULL);
        if (dist<minDist) {
            minDist = dist;
        }
    }

    return minDist;
}
Ejemplo n.º 19
0
//*create Circle from 3 points
//Author: Dongxu Li
bool RS_Circle::createFrom3P(const RS_VectorSolutions& sol) {
    if(sol.getNumber() < 2) return false;
    if(sol.getNumber() == 2) return createFrom2P(sol.get(0),sol.get(1));
    if((sol.get(1)-sol.get(2)).squared() < RS_TOLERANCE*RS_TOLERANCE)
        return createFrom2P(sol.get(0),sol.get(1));
    RS_Vector vra(sol.get(1) - sol.get(0));
    RS_Vector vrb(sol.get(2) - sol.get(0));
    double ra2=vra.squared()*0.5;
    double rb2=vrb.squared()*0.5;
    double crossp=vra.x * vrb.y - vra.y * vrb.x;
    if (fabs(crossp)< RS_TOLERANCE*RS_TOLERANCE) {
        RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Circle::createFrom3P(): "
                        "Cannot create a circle with radius 0.0.");
        return false;
    }
    crossp=1./crossp;
    data.center.set((ra2*vrb.y - rb2*vra.y)*crossp,(rb2*vra.x - ra2*vrb.x)*crossp);
    data.radius=data.center.magnitude();
    data.center += sol.get(0);
    return true;
}
Ejemplo n.º 20
0
/**
//create Ellipse with center and 3 points
*
*
*@Author Dongxu Li
*/
bool	RS_Ellipse::createFromCenter3Points(const RS_VectorSolutions& sol) {
    if(sol.getNumber()<3) return false; //need one center and 3 points on ellipse
    QVector<QVector<double> > mt;
    int mSize(sol.getNumber() -1);
    if( (sol.get(mSize) - sol.get(mSize-1)).squared() < RS_TOLERANCE*RS_TOLERANCE ) {
        //remove the last point
        mSize--;
    }

    mt.resize(mSize);
    QVector<double> dn(mSize);
    switch(mSize){
    case 2:
        for(int i=0;i<mSize;i++){//form the linear equation
            mt[i].resize(mSize+1);
            RS_Vector vp(sol.get(i+1)-sol.get(0)); //the first vector is center
            mt[i][0]=vp.x*vp.x;
            mt[i][1]=vp.y*vp.y;
            mt[i][2]=1.;
        }
        if ( ! RS_Math::linearSolver(mt,dn) ) return false;
        if( dn[0]<RS_TOLERANCE*RS_TOLERANCE || dn[1]<RS_TOLERANCE*RS_TOLERANCE) return false;
        setMajorP(RS_Vector(1./sqrt(dn[0]),0.));
        setRatio(sqrt(dn[0]/dn[1]));
        setAngle1(0.);
        setAngle2(0.);
        setCenter(sol.get(0));
        return true;
        break;
    case 3:
        for(int i=0;i<mSize;i++){//form the linear equation
            mt[i].resize(mSize+1);
            RS_Vector vp(sol.get(i+1)-sol.get(0)); //the first vector is center
            mt[i][0]=vp.x*vp.x;
            mt[i][1]=vp.x*vp.y;
            mt[i][2]=vp.y*vp.y;
            mt[i][3]=1.;
        }
        if ( ! RS_Math::linearSolver(mt,dn) ) return false;
        setCenter(sol.get(0));
        return createFromQuadratic(dn);
    default:
        return false;
    }
}
Ejemplo n.º 21
0
/**
 * @return The intersection which is closest to 'coord' 
 */
RS_Vector RS_EntityContainer::getNearestIntersection(const RS_Vector& coord,
        double* dist) {

    double minDist = RS_MAXDOUBLE;  // minimum measured distance
    double curDist;                 // currently measured distance
    RS_Vector closestPoint(false); // closest found endpoint
    RS_Vector point;                // endpoint found
    RS_VectorSolutions sol;
    RS_Entity* closestEntity;

    closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);

    if (closestEntity!=NULL) {
        for (RS_Entity* en = firstEntity(RS2::ResolveAll);
                en != NULL;
                en = nextEntity(RS2::ResolveAll)) {

            if (en->isVisible() && en!=closestEntity) {
                sol = RS_Information::getIntersection(closestEntity,
                                                      en,
                                                      true);

                for (int i=0; i<4; i++) {
                    point = sol.get(i);
                    if (point.valid) {
                        curDist = coord.distanceTo(point);

                        if (curDist<minDist) {
                            closestPoint = point;
                            minDist = curDist;
                            if (dist!=NULL) {
                                *dist = curDist;
                            }
                        }
                    }
                }
            }
        }
        //}
    }

    return closestPoint;
}
Ejemplo n.º 22
0
RS_Vector RS_Image::getNearestCenter(const RS_Vector& coord,
                                     double* dist) {

    RS_VectorSolutions points;
    RS_VectorSolutions corners = getCorners();
    //bug#485, there's no clear reason to ignore snapping to center within an image
//    if(containsPoint(coord)){
//        //if coord is within image
//        if(dist!=NULL) *dist=0.;
//        return coord;
//    }

    points.push_back((corners.get(0) + corners.get(1))/2.0);
    points.push_back((corners.get(1) + corners.get(2))/2.0);
    points.push_back((corners.get(2) + corners.get(3))/2.0);
    points.push_back((corners.get(3) + corners.get(0))/2.0);
    points.push_back((corners.get(0) + corners.get(2))/2.0);

    return points.getClosest(coord, dist);
}
Ejemplo n.º 23
0
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double& patternOffset) {
    if (painter==NULL || view==NULL) {
        return;
    }

    //only draw the visible portion of line
    QVector<RS_Vector> endPoints(0);
        RS_Vector vpMin(view->toGraph(0,view->getHeight()));
        RS_Vector vpMax(view->toGraph(view->getWidth(),0));
         QPolygonF visualBox(QRectF(vpMin.x,vpMin.y,vpMax.x-vpMin.x, vpMax.y-vpMin.y));
    if( getStartpoint().isInWindowOrdered(vpMin, vpMax) ) endPoints<<getStartpoint();
    if( getEndpoint().isInWindowOrdered(vpMin, vpMax) ) endPoints<<getEndpoint();
    if(endPoints.size()<2){

         QVector<RS_Vector> vertex;
         for(unsigned short i=0;i<4;i++){
             const QPointF& vp(visualBox.at(i));
             vertex<<RS_Vector(vp.x(),vp.y());
         }
         for(unsigned short i=0;i<4;i++){
             RS_Line line(NULL,RS_LineData(vertex.at(i),vertex.at((i+1)%4)));
             auto&& vpIts=RS_Information::getIntersection(static_cast<RS_Entity*>(this), &line, true);
             if( vpIts.size()==0) continue;
             endPoints<<vpIts.get(0);
         }
    }
    if(endPoints.size()<2) return;
    if( (endPoints[0] - getStartpoint()).squared() >
            (endPoints[1] - getStartpoint()).squared() ) std::swap(endPoints[0],endPoints[1]);

    RS_Vector pStart(view->toGui(endPoints.at(0)));
    RS_Vector pEnd(view->toGui(endPoints.at(1)));
    //    std::cout<<"draw line: "<<pStart<<" to "<<pEnd<<std::endl;
    RS_Vector direction=pEnd-pStart;
    if(isHelpLayer(true) && direction.squared() > RS_TOLERANCE){
        //extend line on a help layer to fill the whole view
        RS_Vector lb(0,0);
        RS_Vector rt(view->getWidth(),view->getHeight());
        QList<RS_Vector> rect;
        rect<<lb<<RS_Vector(rt.x,lb.y);
        rect<<rt<<RS_Vector(lb.x,rt.y);
        rect<<lb;
        RS_VectorSolutions sol;
        RS_Line dLine(pStart,pEnd);
        for(int i=0;i<4;i++){
            RS_Line bLine(rect.at(i),rect.at(i+1));
            RS_VectorSolutions sol2=RS_Information::getIntersection(&bLine, &dLine);
            if( sol2.getNumber()>0 && bLine.isPointOnEntity(sol2.get(0),RS_TOLERANCE)) {
                sol.push_back(sol2.get(0));
            }
        }
        switch(sol.getNumber()){
        case 2:
            pStart=sol.get(0);
            pEnd=sol.get(1);
            break;
        case 3:
        case 4:
            pStart=sol.get(0);
            pEnd=sol.get(2);
            break;
        default:
            return;
        }
        direction=pEnd-pStart;
    }
    double  length=direction.magnitude();
    patternOffset -= length;
    if (( !isSelected() && (
              getPen().getLineType()==RS2::SolidLine ||
              view->getDrawingMode()==RS2::ModePreview)) ) {
        //if length is too small, attempt to draw the line, could be a potential bug
        painter->drawLine(pStart,pEnd);
        return;
    }
    //    double styleFactor = getStyleFactor(view);


    // Pattern:
    RS_LineTypePattern* pat;
    if (isSelected()) {
//        styleFactor=1.;
        pat = &patternSelected;
    } else {
        pat = view->getPattern(getPen().getLineType());
    }
    if (pat==NULL) {
//        patternOffset -= length;
        RS_DEBUG->print(RS_Debug::D_WARNING,
                        "RS_Line::draw: Invalid line pattern");
        painter->drawLine(pStart,pEnd);
        return;
    }
//    patternOffset = remainder(patternOffset - length-0.5*pat->totalLength,pat->totalLength)+0.5*pat->totalLength;
    if(length<=RS_TOLERANCE){
        painter->drawLine(pStart,pEnd);
        return; //avoid division by zero
    }
    direction/=length; //cos(angle), sin(angle)
    // Pen to draw pattern is always solid:
    RS_Pen pen = painter->getPen();

    pen.setLineType(RS2::SolidLine);
    painter->setPen(pen);

    // index counter
    int i;

    // pattern segment length:
    double patternSegmentLength = pat->totalLength;

    // create pattern:
    RS_Vector* dp=new RS_Vector[pat->num > 0?pat->num:0];
    double* ds=new double[pat->num > 0?pat->num:0];
    if (pat->num >0 ){
        double dpmm=static_cast<RS_PainterQt*>(painter)->getDpmm();
        for (i=0; i<pat->num; ++i) {
            //        ds[j]=pat->pattern[i] * styleFactor;
            //fixme, styleFactor support needed

            ds[i]=dpmm*pat->pattern[i];
            if( fabs(ds[i]) < 1. ) ds[i] = (ds[i]>=0.)?1.:-1.;
            dp[i] = direction*fabs(ds[i]);
        }
    }else {
        delete[] dp;
        delete[] ds;
        RS_DEBUG->print(RS_Debug::D_WARNING,"invalid line pattern for line, draw solid line instread");
        painter->drawLine(view->toGui(getStartpoint()),
                          view->toGui(getEndpoint()));
        return;
    }
    double total= remainder(patternOffset-0.5*patternSegmentLength,patternSegmentLength) -0.5*patternSegmentLength;
    //    double total= patternOffset-patternSegmentLength;

    RS_Vector p1,p2,p3;
    RS_Vector curP(pStart+direction*total);
    double t2;
    for(int j=0;total<length;j=(j+1)%i) {

        // line segment (otherwise space segment)
        t2=total+fabs(ds[j]);
        p3=curP+dp[j];
        if (ds[j]>0.0 && t2 > 0.0) {
            // drop the whole pattern segment line, for ds[i]<0:
            // trim end points of pattern segment line to line
            p1 =(total > -0.5)? curP:pStart;
            p2 =(t2<length+0.5)?p3:pEnd;
            painter->drawLine(p1,p2);
        }
        total=t2;
        curP=p3;
    }
    delete[] dp;
    delete[] ds;

}
bool RS_ActionPolylineEquidistant::makeContour() {
	if (container==NULL) {
		RS_DEBUG->print("RS_ActionPolylineEquidistant::makeContour: no valid container",
						RS_Debug::D_WARNING);
		return false;
	}

	RS_Vector offset(false);
        QList<RS_Entity*> addList;

	if (document!=NULL) {
		document->startUndoCycle();
	}
	double neg = 1.0;
	if(bRightSide)
		neg = -1.0;
	// Create new entites
	RS_Line line1(NULL, RS_LineData(RS_Vector(true), RS_Vector(true)));
	RS_Line line2(NULL, RS_LineData(RS_Vector(true), RS_Vector(true)));
	for (int num=1;
			num<=number || (number==0 && num<=1);
			num++) {
		RS_Polyline* newPolyline = new RS_Polyline(container);
		newPolyline->setClosed(((RS_Polyline*)originalEntity)->isClosed());
//		newPolyline->setSelected((RS_Polyline*)originalEntity)->isSelected());
		newPolyline->setLayer(((RS_Polyline*)originalEntity)->getLayer());
		newPolyline->setPen(((RS_Polyline*)originalEntity)->getPen());

		bool first = true;
		RS_Entity* lastEntity = ((RS_Polyline*)originalEntity)->lastEntity();
		for (RS_Entity* en=((RS_Polyline*)originalEntity)->firstEntity(); en!=NULL; en=((RS_Polyline*)originalEntity)->nextEntity()) {
			double bulge = 0.0;
			if (en->rtti()==RS2::EntityArc) {
				double r0 = ((RS_Arc*)en)->getRadius();
				double r = r0 - dist*neg;
				if(r < 0)
					break;
				((RS_Arc*)en)->setRadius(r);
				bulge = ((RS_Arc*)en)->getBulge();
				((RS_Arc*)en)->setRadius(r0);
			} else {
				bulge = 0.0;
			}
			RS_Vector v1 = ((RS_AtomicEntity*)en)->getStartpoint();
			RS_Vector v2 = ((RS_AtomicEntity*)en)->getEndpoint();
			offset.set(dist * cos(v1.angleTo(v2)+M_PI*0.5*neg), dist * sin(v1.angleTo(v2)+M_PI*0.5*neg));
			v1.move(offset*num);
			v2.move(offset*num);
			if (first) {
				line1.setStartpoint(v1);
				line1.setEndpoint(v2);
				if(newPolyline->isClosed()){
					RS_Vector v01 = ((RS_AtomicEntity*)lastEntity)->getStartpoint();
					RS_Vector v02 = ((RS_AtomicEntity*)en)->getStartpoint();
					offset.set(dist * cos(v01.angleTo(v02)+M_PI*0.5*neg), dist * sin(v01.angleTo(v02)+M_PI*0.5*neg));
					v01.move(offset*num);
					v02.move(offset*num);
					line2.setStartpoint(v01);
					line2.setEndpoint(v02);
					RS_VectorSolutions vsol = RS_Information::getIntersection(&line1, &line2, false);
					v1 = vsol.get(0);
				}
				newPolyline->setStartpoint(v1);
				newPolyline->addVertex(v1, bulge);
				first = false;
			}else{
				line2.setStartpoint(v1);
				line2.setEndpoint(v2);
				RS_VectorSolutions vsol = RS_Information::getIntersection(&line1, &line2, false);
				RS_Vector v = vsol.get(0);
				newPolyline->addVertex(v, bulge);
				newPolyline->setEndpoint(v);
				line1.setStartpoint(v1);
				line1.setEndpoint(v2);
				if (en==lastEntity/* && newPolyline->isClosed()==false*/){
					newPolyline->addVertex(v2, bulge);
				}
			}
		}
		double bulge = lastEntity->rtti() == RS2::EntityArc? ((RS_Arc*)lastEntity)->getBulge():0.0;
//		newPolyline->setNextBulge(bulge);
		newPolyline->endPolyline();
		container->addEntity(newPolyline);
		document->addUndoable(newPolyline);
	}
	if (document!=NULL) {
		document->endUndoCycle();
	}

	if (graphicView!=NULL) {
		graphicView->redraw();
	}

	return true;
}
Ejemplo n.º 25
0
/**
 * Checks if the given coordinate is inside the given contour.
 *
 * @param point Coordinate to check.
 * @param contour One or more entities which shape a contour.
 *         If the given contour is not closed, the result is undefined.
 *         The entities don't need to be in a specific order.
 * @param onContour Will be set to true if the given point it exactly
 *         on the contour.
 */
bool RS_Information::isPointInsideContour(const RS_Vector& point,
        RS_EntityContainer* contour, bool* onContour) {

    if (contour==NULL) {
        RS_DEBUG->print(RS_Debug::D_WARNING,
                        "RS_Information::isPointInsideContour: contour is NULL");
        return false;
    }

    if (point.x < contour->getMin().x || point.x > contour->getMax().x ||
            point.y < contour->getMin().y || point.y > contour->getMax().y) {
        return false;
    }

    double width = contour->getSize().x+1.0;

    bool sure;
    int counter;
    int tries = 0;
    double rayAngle = 0.0;
    do {
        sure = true;

        // create ray:
        RS_Vector v;
        v.setPolar(width*10.0, rayAngle);
        RS_Line ray(NULL, RS_LineData(point, point+v));
        counter = 0;
        RS_VectorSolutions sol;

        if (onContour!=NULL) {
            *onContour = false;
        }

        for (RS_Entity* e = contour->firstEntity(RS2::ResolveAll);
                e!=NULL;
                e = contour->nextEntity(RS2::ResolveAll)) {

            // intersection(s) from ray with contour entity:
            sol = RS_Information::getIntersection(&ray, e, true);

            for (int i=0; i<=1; ++i) {
                RS_Vector p = sol.get(i);

                if (p.valid) {
                    // point is on the contour itself
                    if (p.distanceTo(point)<1.0e-5) {
                        if (onContour!=NULL) {
                            *onContour = true;
                        }
                    } else {
                        if (e->rtti()==RS2::EntityLine) {
                            RS_Line* line = (RS_Line*)e;

                            // ray goes through startpoint of line:
                            if (p.distanceTo(line->getStartpoint())<1.0e-4) {
                                if (RS_Math::correctAngle(line->getAngle1())<M_PI) {
                                    counter++;
                                    sure = false;
                                }
                            }

                            // ray goes through endpoint of line:
                            else if (p.distanceTo(line->getEndpoint())<1.0e-4) {
                                if (RS_Math::correctAngle(line->getAngle2())<M_PI) {
                                    counter++;
                                    sure = false;
                                }
                            }
                            // ray goes through the line:


                            else {
                                counter++;
                            }
                        } else if (e->rtti()==RS2::EntityArc) {
                            RS_Arc* arc = (RS_Arc*)e;

                            if (p.distanceTo(arc->getStartpoint())<1.0e-4) {
                                double dir = arc->getDirection1();
                                if ((dir<M_PI && dir>=1.0e-5) ||
                                        ((dir>2*M_PI-1.0e-5 || dir<1.0e-5) &&
                                         arc->getCenter().y>p.y)) {
                                    counter++;
                                    sure = false;
                                }
                            }
                            else if (p.distanceTo(arc->getEndpoint())<1.0e-4) {
                                double dir = arc->getDirection2();
                                if ((dir<M_PI && dir>=1.0e-5) ||
                                        ((dir>2*M_PI-1.0e-5 || dir<1.0e-5) &&
                                         arc->getCenter().y>p.y)) {
                                    counter++;
                                    sure = false;
                                }
                            } else {
                                counter++;
                            }
                        } else if (e->rtti()==RS2::EntityCircle) {
                            // tangent:
                            if (i==0 && sol.get(1).valid==false) {
                                if (!sol.isTangent()) {
                                    counter++;
                                } else {
                                    sure = false;
                                }
                            } else if (i==1 || sol.get(1).valid==true) {
                                counter++;
                            }
                        }
                    }
                }
            }
        }

        rayAngle+=0.02;
        tries++;
    }
    while (!sure && rayAngle<2*M_PI && tries<6);

    // remove double intersections:
    /*
       QList<RS_Vector> is2;
       bool done;
    RS_Vector* av;
       do {
           done = true;
           double minDist = RS_MAXDOUBLE;
           double dist;
    	av = NULL;
           for (RS_Vector* v = is.first(); v!=NULL; v = is.next()) {
               dist = point.distanceTo(*v);
               if (dist<minDist) {
                   minDist = dist;
                   done = false;
    			av = v;
               }
           }

    	if (!done && av!=NULL) {
    		is2.append(*av);
    	}
       } while (!done);
    */

    return ((counter%2)==1);
}
Ejemplo n.º 26
0
/**
 * @return One or two intersection points between given entities.
 */
RS_VectorSolutions RS_Information::getIntersectionLineEllipse(RS_Line* line,
        RS_Ellipse* ellipse) {

    RS_VectorSolutions ret;

    if (line==NULL || ellipse==NULL) {
        return ret;
    }

    // rotate into normal position:
    double ang = ellipse->getAngle();

    double rx = ellipse->getMajorRadius();
    double ry = ellipse->getMinorRadius();
    RS_Vector center = ellipse->getCenter();
    RS_Vector a1 = line->getStartpoint().rotate(center, -ang);
    RS_Vector a2 = line->getEndpoint().rotate(center, -ang);
    RS_Vector origin = a1;
    RS_Vector dir = a2-a1;
    RS_Vector diff = origin - center;
    RS_Vector mDir = RS_Vector(dir.x/(rx*rx), dir.y/(ry*ry));
    RS_Vector mDiff = RS_Vector(diff.x/(rx*rx), diff.y/(ry*ry));

    double a = RS_Vector::dotP(dir, mDir);
    double b = RS_Vector::dotP(dir, mDiff);
    double c = RS_Vector::dotP(diff, mDiff) - 1.0;
    double d = b*b - a*c;

    if (d < 0) {
        RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 0");
    } else if ( d > 0 ) {
        double root = sqrt(d);
        double t_a = (-b - root) / a;
        double t_b = (-b + root) / a;

        /*if ( (t_a < 0 || 1 < t_a) && (t_b < 0 || 1 < t_b) ) {
            if ( (t_a < 0 && t_b < 0) || (t_a > 1 && t_b > 1) ) {
                RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 1");
            }
            else {
                RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: inside 1");
            }
        } else {*/
        RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: intersection 1");
        RS_Vector ret1(false);
        RS_Vector ret2(false);
        //if ( 0 <= t_a && t_a <= 1 ) {
        //RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t_a<=1");
        ret1 = a1.lerp(a2, t_a);
        RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret1: %f/%f", ret1.x, ret1.y);
        //}
        //if ( 0 <= t_b && t_b <= 1 ) {
        //RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t_b<=1");
        ret2 = a1.lerp(a2, t_b);
        RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret2: %f/%f", ret2.x, ret2.y);
        //}
        if (ret1.valid && ret2.valid) {
            ret = RS_VectorSolutions(ret1, ret2);
        }
        else {
            if (ret1.valid) {
                ret = RS_VectorSolutions(ret1);
            }
            if (ret2.valid) {
                ret = RS_VectorSolutions(ret2);
            }
        }
        //}
    } else {
        double t = -b/a;
        if ( 0 <= t && t <= 1 ) {
            RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: 0<=t<=1");
            RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: intersection 2");
            ret = RS_VectorSolutions(a1.lerp(a2, t));
            RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: ret1: %f/%f", ret.get(0).x, ret.get(0).y);
        } else {
            RS_DEBUG->print("RS_Information::getIntersectionLineEllipse: outside 2");
        }
    }

    ret.rotate(center, ang);
    return ret;



    /*
    RS_Arc* arc = new RS_Arc(NULL,
                             RS_ArcData(ellipse->getCenter(),
                                        ellipse->getMajorRadius(),
                                        ellipse->getAngle1(),
                                        ellipse->getAngle2(),
                                        false));
    RS_Line* other = (RS_Line*)line->clone();
    double angle = ellipse->getAngle();
    //double ratio = ellipse->getRatio();

    // rotate entities:
    other->rotate(ellipse->getCenter(), -angle);
    other->scale(ellipse->getCenter(), RS_Vector(1.0, 1.0/ellipse->getRatio()));

    ret = getIntersectionLineArc(other, arc);

    ret.scale(ellipse->getCenter(), RS_Vector(1.0, ellipse->getRatio()));
    ret.rotate(ellipse->getCenter(), angle);

    delete arc;
    delete other;

    return ret;
    */
}
Ejemplo n.º 27
0
/**
 * Calculates the intersection point(s) between two entities.
 *
 * @param onEntities true: only return intersection points which are
 *                   on both entities.
 *                   false: return all intersection points.
 *
 * @todo support more entities
 *
 * @return All intersections of the two entities. The tangent flag in
 * RS_VectorSolutions is set if one intersection is a tangent point.
 */
RS_VectorSolutions RS_Information::getIntersection(RS_Entity* e1,
        RS_Entity* e2, bool onEntities) {

    RS_VectorSolutions ret;
    double tol = 1.0e-4;

    if (e1==NULL || e2==NULL ) {
        RS_DEBUG->print("RS_Information::getIntersection() for NULL entities");
        return ret;
    }
    if (e1->getId() == e2->getId()) {
        RS_DEBUG->print("RS_Information::getIntersection() of the same entity");
        return ret;
    }

    // unsupported entities / entity combinations:
    if (
        e1->rtti()==RS2::EntityText || e2->rtti()==RS2::EntityText ||
        isDimension(e1->rtti()) || isDimension(e2->rtti())) {
        return ret;
    }
    // a little check to avoid doing unneeded intersections, an attempt to avoid O(N^2) increasing of checking two-entity information
    if (onEntities
            && (
                e1 -> getMin().x > e2 -> getMax().x
                || e1 -> getMax().x < e2 -> getMin().x
                || e1 -> getMin().y > e2 -> getMax().y
                || e1 -> getMax().y < e2 -> getMin().y
                )
            ) {
            return ret;
    }

    // one entity is an ellipse:
    if (e1->rtti()==RS2::EntityEllipse || e2->rtti()==RS2::EntityEllipse) {
        if (e2->rtti()==RS2::EntityEllipse) std::swap( e1, e2);
        if (e2->rtti()==RS2::EntityEllipse) {
            ret = getIntersectionEllipseEllipse((RS_Ellipse*)e1, (RS_Ellipse *) e2);
        }
        if (e2->rtti()==RS2::EntityCircle) {
            ret = getIntersectionCircleEllipse((RS_Circle *)e2, (RS_Ellipse *) e1);
        }
        if (e2->rtti()==RS2::EntityArc) {
            ret = getIntersectionArcEllipse((RS_Arc *)e2, (RS_Ellipse *) e1);
        }
        if (e2->rtti()==RS2::EntityLine) {
            ret = getIntersectionLineEllipse((RS_Line*)e2, (RS_Ellipse*) e1);
            tol = 1.0e-1;
        }

        // not supported:
        else {
            return ret;
        }
    } else {

        RS_Entity* te1 = e1;
        RS_Entity* te2 = e2;

        // entity copies - so we only have to deal with lines and arcs
        RS_Line l1(NULL,
                   RS_LineData(RS_Vector(0.0, 0.0), RS_Vector(0.0,0.0)));
        RS_Line l2(NULL,
                   RS_LineData(RS_Vector(0.0, 0.0), RS_Vector(0.0,0.0)));

        RS_Arc a1(NULL,
                  RS_ArcData(RS_Vector(0.0,0.0), 1.0, 0.0, 2*M_PI, false));
        RS_Arc a2(NULL,
                  RS_ArcData(RS_Vector(0.0,0.0), 1.0, 0.0, 2*M_PI, false));

        // convert construction lines to lines:
        if (e1->rtti()==RS2::EntityConstructionLine) {
            RS_ConstructionLine* cl = (RS_ConstructionLine*)e1;

            l1.setStartpoint(cl->getPoint1());
            l1.setEndpoint(cl->getPoint2());

            te1 = &l1;
        }
        if (e2->rtti()==RS2::EntityConstructionLine) {
            RS_ConstructionLine* cl = (RS_ConstructionLine*)e2;

            l2.setStartpoint(cl->getPoint1());
            l2.setEndpoint(cl->getPoint2());

            te2 = &l2;
        }


        // convert circles to arcs:
        if (e1->rtti()==RS2::EntityCircle) {
            RS_Circle* c = (RS_Circle*)e1;

            RS_ArcData data(c->getCenter(), c->getRadius(), 0.0, 2*M_PI, false);
            a1.setData(data);

            te1 = &a1;
        }
        if (e2->rtti()==RS2::EntityCircle) {
            RS_Circle* c = (RS_Circle*)e2;

            RS_ArcData data(c->getCenter(), c->getRadius(), 0.0, 2*M_PI, false);
            a2.setData(data);

            te2 = &a2;
        }


        // line / line:
        //
        //else
        if (te1->rtti()==RS2::EntityLine &&
                te2->rtti()==RS2::EntityLine) {
            RS_Line * line1=(RS_Line*) te1;
            RS_Line * line2=(RS_Line*) te2;
            /* ToDo: 24 Aug 2011, Dongxu Li, if rtti() is not defined for the parent, the following check for splines may still cause segfault */
            if ( line1->getParent() != NULL && line1->getParent() == line2->getParent()) {
                if ( line1->getParent()->rtti()==RS2::EntitySpline ) {
                    //do not calculate intersections from neighboring lines of a spline
                    if ( abs(line1->getParent()->findEntity(line1) - line1->getParent()->findEntity(line2)) <= 1 ) {
                        return ret;
                    }
                }
            }

            ret = getIntersectionLineLine(line1, line2);
        }

        // line / arc:
        //
        else if (te1->rtti()==RS2::EntityLine &&
                 te2->rtti()==RS2::EntityArc) {

            RS_Line* line = (RS_Line*)te1;
            RS_Arc* arc = (RS_Arc*)te2;

            ret = getIntersectionLineArc(line, arc);
        }

        // arc / line:
        //
        else if (te1->rtti()==RS2::EntityArc &&
                 te2->rtti()==RS2::EntityLine) {

            RS_Arc* arc = (RS_Arc*)te1;
            RS_Line* line = (RS_Line*)te2;

            ret = getIntersectionLineArc(line, arc);
        }

        // arc / arc:
        //
        else if (te1->rtti()==RS2::EntityArc &&
                 te2->rtti()==RS2::EntityArc) {

            RS_Arc* arc1 = (RS_Arc*)te1;
            RS_Arc* arc2 = (RS_Arc*)te2;

            ret = getIntersectionArcArc(arc1, arc2);
            // ellipse / ellipse
            //
        } else {
            RS_DEBUG->print("RS_Information::getIntersection:: Unsupported entity type.");
        }

    }


    // Check all intersection points for being on entities:
    //
    if (onEntities==true) {
        if (!e1->isPointOnEntity(ret.get(0), tol) ||
                !e2->isPointOnEntity(ret.get(0), tol)) {
            ret.set(0, RS_Vector(false));
        }
        if (!e1->isPointOnEntity(ret.get(1), tol) ||
                !e2->isPointOnEntity(ret.get(1), tol)) {
            ret.set(1, RS_Vector(false));
        }
        if (!e1->isPointOnEntity(ret.get(2), tol) ||
                !e2->isPointOnEntity(ret.get(2), tol)) {
            ret.set(2, RS_Vector(false));
        }
        if (!e1->isPointOnEntity(ret.get(3), tol) ||
                !e2->isPointOnEntity(ret.get(3), tol)) {
            ret.set(3, RS_Vector(false));
        }
    }

    int k=0;
    for (int i=0; i<4; ++i) {
        if (ret.get(i).valid) {
            ret.set(k, ret.get(i));
            k++;
        }
    }
    for (int i=k; i<4; ++i) {
        ret.set(i, RS_Vector(false));
    }

    return ret;
}
Ejemplo n.º 28
0
void RS_ActionDimAngular::mouseReleaseEvent(QMouseEvent* e) {

    if (e->button()==Qt::LeftButton) {
        switch (getStatus()) {
        case SetLine1: {
                RS_Entity* en = catchEntity(e, RS2::ResolveAll);
                if (en!=NULL &&
                        en->rtti()==RS2::EntityLine) {
                    line1 = (RS_Line*)en;
                    setStatus(SetLine2);
                }
            }
            break;

        case SetLine2: {
                RS_Entity* en = catchEntity(e, RS2::ResolveAll);
                if (en!=NULL &&
                        en->rtti()==RS2::EntityLine) {
                    line2 = (RS_Line*)en;

                    RS_VectorSolutions sol =
                        RS_Information::getIntersectionLineLine(line1, line2);

                    if (sol.get(0).valid) {
                        center = sol.get(0);

                        if (center.distanceTo(line1->getStartpoint()) <
                                center.distanceTo(line1->getEndpoint())) {
							edata->definitionPoint1 = line1->getStartpoint();
							edata->definitionPoint2 = line1->getEndpoint();
                        } else {
							edata->definitionPoint1 = line1->getEndpoint();
							edata->definitionPoint2 = line1->getStartpoint();
                        }

                        if (center.distanceTo(line2->getStartpoint()) <
                                center.distanceTo(line2->getEndpoint())) {
							edata->definitionPoint3 = line2->getStartpoint();
							data->definitionPoint = line2->getEndpoint();
                        } else {
							edata->definitionPoint3 = line2->getEndpoint();
							data->definitionPoint = line2->getStartpoint();
                        }
                        graphicView->moveRelativeZero(center);
                        setStatus(SetPos);
                    }
                }
            }
            break;

        case SetPos: {
                RS_CoordinateEvent ce(snapPoint(e));
                coordinateEvent(&ce);
            }
            break;
        }
    } else if (e->button()==Qt::RightButton) {
        deletePreview();
        init(getStatus()-1);
    }

}
Ejemplo n.º 29
0
/**
 * Updates the Hatch. Called when the
 * hatch or it's data, position, alignment, .. changes.
 */
void RS_Hatch::update() {
        RS_DEBUG->print("RS_Hatch::update");
        RS_DEBUG->print("RS_Hatch::update: contour has %d loops", count());

    updateError = HATCH_OK;
    if (updateRunning) {
        return;
    }

    if (updateEnabled==false) {
        return;
    }

    if (data.solid==true) {
        calculateBorders();
        return;
    }

    RS_DEBUG->print("RS_Hatch::update");
    updateRunning = true;

    // delete old hatch:
    if (hatch!=NULL) {
        removeEntity(hatch);
        hatch = NULL;
    }

    if (isUndone()) {
        updateRunning = false;
        return;
    }

    if (!validate()) {
        RS_DEBUG->print(RS_Debug::D_WARNING,
                        "RS_Hatch::update: invalid contour in hatch found");
        updateRunning = false;
        updateError = HATCH_INVALID_CONTOUR;
        return;
    }

    // search pattern:
    RS_DEBUG->print("RS_Hatch::update: requesting pattern");
    RS_Pattern* pat = RS_PATTERNLIST->requestPattern(data.pattern);
    if (pat==NULL) {
        updateRunning = false;
        RS_DEBUG->print("RS_Hatch::update: requesting pattern: not found");
        updateError = HATCH_PATTERN_NOT_FOUND;
        return;
    }
    RS_DEBUG->print("RS_Hatch::update: requesting pattern: OK");

    RS_DEBUG->print("RS_Hatch::update: cloning pattern");
    pat = (RS_Pattern*)pat->clone();
    RS_DEBUG->print("RS_Hatch::update: cloning pattern: OK");

    // scale pattern
    RS_DEBUG->print("RS_Hatch::update: scaling pattern");
    pat->scale(RS_Vector(0.0,0.0), RS_Vector(data.scale, data.scale));
    pat->calculateBorders();
    forcedCalculateBorders();
    RS_DEBUG->print("RS_Hatch::update: scaling pattern: OK");

    // find out how many pattern-instances we need in x/y:
    int px1, py1, px2, py2;
    double f;
    RS_Hatch* copy = (RS_Hatch*)this->clone();
    copy->rotate(RS_Vector(0.0,0.0), -data.angle);
    copy->forcedCalculateBorders();

    // create a pattern over the whole contour.
    RS_Vector pSize = pat->getSize();
    RS_Vector rot_center=pat->getMin();
//    RS_Vector cPos = getMin();
    RS_Vector cSize = getSize();


    RS_DEBUG->print("RS_Hatch::update: pattern size: %f/%f", pSize.x, pSize.y);
    RS_DEBUG->print("RS_Hatch::update: contour size: %f/%f", cSize.x, cSize.y);

    if (cSize.x<1.0e-6 || cSize.y<1.0e-6 ||
            pSize.x<1.0e-6 || pSize.y<1.0e-6 ||
            cSize.x>RS_MAXDOUBLE-1 || cSize.y>RS_MAXDOUBLE-1 ||
            pSize.x>RS_MAXDOUBLE-1 || pSize.y>RS_MAXDOUBLE-1) {
        delete pat;
        delete copy;
        updateRunning = false;
        RS_DEBUG->print("RS_Hatch::update: contour size or pattern size too small");
        updateError = HATCH_TOO_SMALL;
        return;
    }

    // avoid huge memory consumption:
    else if ( cSize.x* cSize.y/(pSize.x*pSize.y)>1e4) {
        RS_DEBUG->print("RS_Hatch::update: contour size too large or pattern size too small");
        updateError = HATCH_AREA_TOO_BIG;
        return;
    }

    f = copy->getMin().x/pat->getSize().x;
    px1 = (int)floor(f);
    f = copy->getMin().y/pat->getSize().y;
    py1 = (int)floor(f);
    f = copy->getMax().x/pat->getSize().x;
    px2 = (int)ceil(f);
    f = copy->getMax().y/pat->getSize().y;
    py2 = (int)ceil(f);
    RS_Vector dvx=RS_Vector(data.angle)*pSize.x;
    RS_Vector dvy=RS_Vector(data.angle+M_PI*0.5)*pSize.y;
    pat->rotate(rot_center, data.angle);
    pat->move(-rot_center);


    RS_EntityContainer tmp;   // container for untrimmed lines

    // adding array of patterns to tmp:
    RS_DEBUG->print("RS_Hatch::update: creating pattern carpet");

    for (int px=px1; px<=px2; px++) {
        for (int py=py1; py<=py2; py++) {
            for (RS_Entity* e=pat->firstEntity(); e!=NULL;
                    e=pat->nextEntity()) {
                RS_Entity* te=e->clone();
                te->move(dvx*px + dvy*py);
                tmp.addEntity(te);
            }
        }
    }

    delete pat;
    pat = NULL;
    RS_DEBUG->print("RS_Hatch::update: creating pattern carpet: OK");


    RS_DEBUG->print("RS_Hatch::update: cutting pattern carpet");
    // cut pattern to contour shape:
    RS_EntityContainer tmp2;   // container for small cut lines
    RS_Line* line = NULL;
    RS_Arc* arc = NULL;
    RS_Circle* circle = NULL;
    RS_Ellipse* ellipse = NULL;
    for (RS_Entity* e=tmp.firstEntity(); e!=NULL;
            e=tmp.nextEntity()) {

        RS_Vector startPoint;
        RS_Vector endPoint;
        RS_Vector center = RS_Vector(false);
        bool reversed=false;

        switch(e->rtti()){
        case RS2::EntityLine:
            line=static_cast<RS_Line*>(e);
            startPoint = line->getStartpoint();
            endPoint = line->getEndpoint();
            break;
        case RS2::EntityArc:
            arc=static_cast<RS_Arc*>(e);
            startPoint = arc->getStartpoint();
            endPoint = arc->getEndpoint();
            center = arc->getCenter();
            reversed = arc->isReversed();
            break;
        case RS2::EntityCircle:
            circle=static_cast<RS_Circle*>(e);
            startPoint = circle->getCenter()
                    + RS_Vector(circle->getRadius(), 0.0);
            endPoint = startPoint;
            center = circle->getCenter();
            break;
        case RS2::EntityEllipse:
            ellipse = static_cast<RS_Ellipse*>(e);
            startPoint = ellipse->getStartpoint();
            endPoint = ellipse->getEndpoint();
            center = ellipse->getCenter();
            reversed = ellipse->isReversed();
            break;
        default:
            continue;
        }

        // getting all intersections of this pattern line with the contour:
        QList<std::shared_ptr<RS_Vector> > is;
        is.append(std::shared_ptr<RS_Vector>(new RS_Vector(startPoint)));

        for (RS_Entity* loop=firstEntity(); loop!=NULL;
                loop=nextEntity()) {

            if (loop->isContainer()) {
                for (RS_Entity* p=((RS_EntityContainer*)loop)->firstEntity();
                        p!=NULL;
                        p=((RS_EntityContainer*)loop)->nextEntity()) {

                    RS_VectorSolutions sol =
                        RS_Information::getIntersection(e, p, true);

                    for (int i=0; i<=1; ++i) {
                        if (sol.get(i).valid) {
                            is.append(std::shared_ptr<RS_Vector>(
                                          new RS_Vector(sol.get(i))
                                                        ));
                            RS_DEBUG->print("  pattern line intersection: %f/%f",
                                            sol.get(i).x, sol.get(i).y);
                        }
                    }
                }
            }
        }

        is.append(std::shared_ptr<RS_Vector>(new RS_Vector(endPoint)));

        // sort the intersection points into is2:
        RS_Vector sp = startPoint;
        double sa = center.angleTo(sp);
        if(ellipse != NULL) sa=ellipse->getEllipseAngle(sp);
        QList<std::shared_ptr<RS_Vector> > is2;
        bool done;
        double minDist;
        double dist = 0.0;
        std::shared_ptr<RS_Vector> av;
        std::shared_ptr<RS_Vector> v;
        RS_Vector last = RS_Vector(false);
        do {
            done = true;
            minDist = RS_MAXDOUBLE;
            av.reset();
            for (int i = 0; i < is.size(); ++i) {
                v = is.at(i);
                double a;
                switch(e->rtti()){
                case RS2::EntityLine:
                    dist = sp.distanceTo(*v);
                    break;
                case RS2::EntityArc:
                case RS2::EntityCircle:
                    a = center.angleTo(*v);
                    dist = reversed?
                                fmod(sa - a + 2.*M_PI,2.*M_PI):
                                fmod(a - sa + 2.*M_PI,2.*M_PI);
                    break;
                case RS2::EntityEllipse:
                    a = ellipse->getEllipseAngle(*v);
                    dist = reversed?
                                fmod(sa - a + 2.*M_PI,2.*M_PI):
                                fmod(a - sa + 2.*M_PI,2.*M_PI);
                    break;
                default:
                    break;

                }

                if (dist<minDist) {
                    minDist = dist;
                    done = false;
                    av = v;
                }
            }

            // copy to sorted list, removing double points
            if (!done && av.get()!=NULL) {
                if (last.valid==false || last.distanceTo(*av)>RS_TOLERANCE) {
                    is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(*av)));
                    last = *av;
                }
#if QT_VERSION < 0x040400
                emu_qt44_removeOne(is, av);
#else
                is.removeOne(av);
#endif

                av.reset();
            }
        } while(!done);

        // add small cut lines / arcs to tmp2:
            for (int i = 1; i < is2.size(); ++i) {
                auto v1 = is2.at(i-1);
                auto v2 = is2.at(i);

                if (line!=NULL) {
                    tmp2.addEntity(new RS_Line(&tmp2,
                                               RS_LineData(*v1, *v2)));
                } else if (arc!=NULL || circle!=NULL) {
                    tmp2.addEntity(new RS_Arc(&tmp2,
                                              RS_ArcData(center,
                                                         center.distanceTo(*v1),
                                                         center.angleTo(*v1),
                                                         center.angleTo(*v2),
                                                         reversed)));
                }
            }

    }

    // updating hatch / adding entities that are inside
    RS_DEBUG->print("RS_Hatch::update: cutting pattern carpet: OK");

    //RS_EntityContainer* rubbish = new RS_EntityContainer(getGraphic());

    // the hatch pattern entities:
    hatch = new RS_EntityContainer(this);
    hatch->setPen(RS_Pen(RS2::FlagInvalid));
    hatch->setLayer(NULL);
    hatch->setFlag(RS2::FlagTemp);

    //calculateBorders();

    for (RS_Entity* e=tmp2.firstEntity(); e!=NULL;
            e=tmp2.nextEntity()) {

        RS_Vector middlePoint;
        RS_Vector middlePoint2;
        if (e->rtti()==RS2::EntityLine) {
            RS_Line* line = (RS_Line*)e;
            middlePoint = line->getMiddlePoint();
            middlePoint2 = line->getNearestDist(line->getLength()/2.1,
                                                line->getStartpoint());
        } else if (e->rtti()==RS2::EntityArc) {
            RS_Arc* arc = (RS_Arc*)e;
            middlePoint = arc->getMiddlePoint();
            middlePoint2 = arc->getNearestDist(arc->getLength()/2.1,
                                               arc->getStartpoint());
        } else {
            middlePoint = RS_Vector(false);
            middlePoint2 = RS_Vector(false);
        }

        if (middlePoint.valid) {
            bool onContour=false;

            if (RS_Information::isPointInsideContour(
                        middlePoint,
                        this, &onContour) ||
                    RS_Information::isPointInsideContour(middlePoint2, this)) {

                RS_Entity* te = e->clone();
                te->setPen(RS_Pen(RS2::FlagInvalid));
                te->setLayer(NULL);
                te->reparent(hatch);
                hatch->addEntity(te);
            }
        }
    }

    addEntity(hatch);
    //getGraphic()->addEntity(rubbish);

    forcedCalculateBorders();

    // deactivate contour:
    activateContour(false);

    updateRunning = false;

    RS_DEBUG->print("RS_Hatch::update: OK");
}
Ejemplo n.º 30
0
RS_Vector RS_Ellipse::prepareTrim(const RS_Vector& trimCoord,
                                  const RS_VectorSolutions& trimSol) {
//special trimming for ellipse arc
        RS_DEBUG->print("RS_Ellipse::prepareTrim()");
    if( ! trimSol.hasValid() ) return (RS_Vector(false));
    if( trimSol.getNumber() == 1 ) return (trimSol.get(0));
    double am=getEllipseAngle(trimCoord);
    QList<double> ias;
    double ia(0.),ia2(0.);
    RS_Vector is,is2;
    for(int ii=0; ii<trimSol.getNumber(); ii++) { //find closest according ellipse angle
        ias.append(getEllipseAngle(trimSol.get(ii)));
        if( !ii ||  fabs( remainder( ias[ii] - am, 2*M_PI)) < fabs( remainder( ia -am, 2*M_PI)) ) {
            ia = ias[ii];
            is = trimSol.get(ii);
        }
    }
    qSort(ias.begin(),ias.end());
    for(int ii=0; ii<trimSol.getNumber(); ii++) { //find segment to enclude trimCoord
        if ( ! RS_Math::isSameDirection(ia,ias[ii],RS_TOLERANCE)) continue;
        if( RS_Math::isAngleBetween(am,ias[(ii+trimSol.getNumber()-1)% trimSol.getNumber()],ia,false))  {
            ia2=ias[(ii+trimSol.getNumber()-1)% trimSol.getNumber()];
        } else {
            ia2=ias[(ii+1)% trimSol.getNumber()];
        }
        break;
    }
    for(int ii=0; ii<trimSol.getNumber(); ii++) { //find segment to enclude trimCoord
        if ( ! RS_Math::isSameDirection(ia2,getEllipseAngle(trimSol.get(ii)),RS_TOLERANCE)) continue;
        is2=trimSol.get(ii);
        break;
    }
    if(RS_Math::isSameDirection(getAngle1(),getAngle2(),RS_TOLERANCE_ANGLE)
            ||  RS_Math::isSameDirection(ia2,ia,RS_TOLERANCE) ) {
        //whole ellipse
        if( !RS_Math::isAngleBetween(am,ia,ia2,isReversed())) {
            std::swap(ia,ia2);
            std::swap(is,is2);
        }
        setAngle1(ia);
        setAngle2(ia2);
        double da1=fabs(remainder(getAngle1()-am,2*M_PI));
        double da2=fabs(remainder(getAngle2()-am,2*M_PI));
        if(da2<da1) {
            std::swap(is,is2);
        }

    } else {
        double dia=fabs(remainder(ia-am,2*M_PI));
        double dia2=fabs(remainder(ia2-am,2*M_PI));
        double ai_min=std::min(dia,dia2);
        double da1=fabs(remainder(getAngle1()-am,2*M_PI));
        double da2=fabs(remainder(getAngle2()-am,2*M_PI));
        double da_min=std::min(da1,da2);
        if( da_min < ai_min ) {
            //trimming one end of arc
            bool irev= RS_Math::isAngleBetween(am,ia2,ia, isReversed()) ;
            if ( RS_Math::isAngleBetween(ia,getAngle1(),getAngle2(), isReversed()) &&
                    RS_Math::isAngleBetween(ia2,getAngle1(),getAngle2(), isReversed()) ) { //
                if(irev) {
                    setAngle2(ia);
                    setAngle1(ia2);
                } else {
                    setAngle1(ia);
                    setAngle2(ia2);
                }
                da1=fabs(remainder(getAngle1()-am,2*M_PI));
                da2=fabs(remainder(getAngle2()-am,2*M_PI));
            }
            if( ((da1 < da2) && (RS_Math::isAngleBetween(ia2,ia,getAngle1(),isReversed()))) ||
                    ((da1 > da2) && (RS_Math::isAngleBetween(ia2,getAngle2(),ia,isReversed())))
              ) {
                std::swap(is,is2);
                //std::cout<<"reset: angle1="<<getAngle1()<<" angle2="<<getAngle2()<<" am="<< am<<" is="<<getEllipseAngle(is)<<" ia2="<<ia2<<std::endl;
            }
        } else {
            //choose intersection as new end
            if( dia > dia2) {
                std::swap(is,is2);
                std::swap(ia,ia2);
            }
            if(RS_Math::isAngleBetween(ia,getAngle1(),getAngle2(),isReversed())) {
                if(RS_Math::isAngleBetween(am,getAngle1(),ia,isReversed())) {
                    setAngle2(ia);
                } else {
                    setAngle1(ia);
                }
            }
        }
    }
    return is;
}