Пример #1
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;

  double styleFactor = view->getStyleFactor();    /* ++++++++++++++++ new added, in SETTINGS adapt. */

    // 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 * styleFactor * 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;

}
void RS_ActionDrawEllipseAxis::mouseMoveEvent(QMouseEvent* e) {
    RS_DEBUG->print("RS_ActionDrawEllipseAxis::mouseMoveEvent begin");

    RS_Vector mouse = snapPoint(e);

    switch (getStatus()) {
//    case SetCenter:
//        break;

    case SetMajor:
        if (center.valid) {
            deletePreview();
            RS_EllipseData ed(center, mouse-center,
                              0.5,
                              0.0, isArc?2.*M_PI:0.0,
                              false);
			preview->addEntity(new RS_Ellipse(preview.get(), ed));
            drawPreview();
        }
        break;

    case SetMinor:
        if (center.valid && major.valid) {
            deletePreview();
            RS_Line line(NULL, RS_LineData(center-major, center+major));
            double d = line.getDistanceToPoint(mouse);
            ratio = d/(line.getLength()/2);
            RS_EllipseData ed(center, major,
                              ratio,
                              0.0, isArc?2.*M_PI:0.0,
                              false);
			preview->addEntity(new RS_Ellipse(preview.get(), ed));
            drawPreview();
        }
        break;

    case SetAngle1:
        if (center.valid && major.valid) {
            deletePreview();

            //angle1 = center.angleTo(mouse);

                        RS_Vector m = mouse;
                        m.rotate(center, -major.angle());
                        RS_Vector v = m-center;
                        v.scale(RS_Vector(1.0, 1.0/ratio));
                        angle1 = v.angle(); // + major.angle();

			preview->addEntity(new RS_Line(preview.get(), RS_LineData(center, mouse)));

            RS_EllipseData ed(center, major,
                              ratio,
                              angle1, angle1+1.0,
                              false);
			preview->addEntity(new RS_Ellipse(preview.get(), ed));
            drawPreview();
        }
        break;

    case SetAngle2:
        if (center.valid && major.valid) {
            deletePreview();
            //angle2 = center.angleTo(mouse);

                        RS_Vector m = mouse;
                        m.rotate(center, -major.angle());
                        RS_Vector v = m-center;
                        v.scale(RS_Vector(1.0, 1.0/ratio));
                        angle2 = v.angle(); // + major.angle();

			preview->addEntity(new RS_Line(preview.get(), RS_LineData(center, mouse)));

            RS_EllipseData ed(
                center, major,
                ratio,
                angle1, angle2,
                false);
			preview->addEntity(new RS_Ellipse(preview.get(), ed));
            drawPreview();
        }

    default:
        break;
    }

    RS_DEBUG->print("RS_ActionDrawEllipseAxis::mouseMoveEvent end");
}
void RS_ActionModifyStretch::mouseMoveEvent(QMouseEvent* e) {
    RS_DEBUG->print("RS_ActionModifyStretch::mouseMoveEvent begin");

    RS_Vector mouse = snapPoint(e);
    switch (getStatus()) {
    case SetFirstCorner:
        break;

    case SetSecondCorner:
        if (firstCorner.valid) {
            secondCorner = snapPoint(e);
            deletePreview();
            preview->addEntity(
                new RS_Line(preview,
                            RS_LineData(RS_Vector(firstCorner.x,
                                                  firstCorner.y),
                                        RS_Vector(secondCorner.x,
                                                  firstCorner.y))));
            preview->addEntity(
                new RS_Line(preview,
                            RS_LineData(RS_Vector(secondCorner.x,
                                                  firstCorner.y),
                                        RS_Vector(secondCorner.x,
                                                  secondCorner.y))));
            preview->addEntity(
                new RS_Line(preview,
                            RS_LineData(RS_Vector(secondCorner.x,
                                                  secondCorner.y),
                                        RS_Vector(firstCorner.x,
                                                  secondCorner.y))));
            preview->addEntity(
                new RS_Line(preview,
                            RS_LineData(RS_Vector(firstCorner.x,
                                                  secondCorner.y),
                                        RS_Vector(firstCorner.x,
                                                  firstCorner.y))));
            drawPreview();
        }
        break;

    case SetReferencePoint:
        break;

    case SetTargetPoint:
        if (referencePoint.valid) {
            targetPoint = mouse;

            deletePreview();
            preview->addStretchablesFrom(*container, firstCorner, secondCorner);
            //preview->move(targetPoint-referencePoint);
            preview->stretch(firstCorner, secondCorner,
                             targetPoint-referencePoint);
            drawPreview();
        }
        break;

    default:
        break;
    }

    RS_DEBUG->print("RS_ActionModifyStretch::mouseMoveEvent end");
}
Пример #4
0
/**
 * Updates the sub entities of this dimension. Called when the
 * dimension or the position, alignment, .. changes.
 *
 * @param autoText Automatically reposition the text label
 */
void RS_DimRadial::updateDim(bool autoText) {

    RS_DEBUG->print("RS_DimRadial::update");

    clear();

    if (isUndone()) {
        return;
    }

    // dimension line:
    //updateCreateDimensionLine(data.definitionPoint, edata.definitionPoint,
    //false, true);

    // general scale (DIMSCALE)
    double dimscale = getGeneralScale();

	RS_Vector p1 = data.definitionPoint;
    RS_Vector p2 = edata.definitionPoint;
    double angle = p1.angleTo(p2);

    // text height (DIMTXT)
    double dimtxt = getTextHeight()*dimscale;
    // text distance to line (DIMGAP)
    double dimgap = getDimensionLineGap()*dimscale;
    // arrow size:
    double arrowSize = getArrowSize()*dimscale;

    // length of dimension line:
    double length = p1.distanceTo(p2);

    RS_MTextData textData;

    textData = RS_MTextData(RS_Vector(0.0,0.0),
                           dimtxt, 30.0,
                           RS_MTextData::VAMiddle,
                           RS_MTextData::HACenter,
                           RS_MTextData::LeftToRight,
                           RS_MTextData::Exact,
                           1.0,
                           getLabel(),
                           "standard",
                           0.0);

    RS_MText* text = new RS_MText(this, textData);
    double textWidth = text->getSize().x;

    // do we have to put the arrow / text outside of the arc?
    bool outsideArrow = (length<arrowSize*2+textWidth);
    double arrowAngle;

    if (outsideArrow) {
        length += arrowSize*2 + textWidth;
        arrowAngle = angle+M_PI;
    } else {
        arrowAngle = angle;
    }

    // create arrow:
    RS_SolidData sd;
    RS_Solid* arrow;

    arrow = new RS_Solid(this, sd);
    arrow->shapeArrow(p2,
                      arrowAngle,
                      arrowSize);
    arrow->setPen(RS_Pen(RS2::FlagInvalid));
    arrow->setLayer(NULL);
    addEntity(arrow);

    RS_Vector p3;
    p3.setPolar(length, angle);
    p3 += p1;

    // Create dimension line:
    RS_Line* dimensionLine = new RS_Line(this, RS_LineData(p1, p3));
    dimensionLine->setPen(RS_Pen(RS2::FlagInvalid));
    dimensionLine->setLayer(NULL);
    addEntity(dimensionLine);

    RS_Vector distV;
    double textAngle;

    // rotate text so it's readable from the bottom or right (ISO)
    // quadrant 1 & 4
	if (angle>M_PI_2*3.0+0.001 ||
			angle<M_PI_2+0.001) {

		distV.setPolar(dimgap + dimtxt/2.0, angle+M_PI_2);
        textAngle = angle;
    }
    // quadrant 2 & 3
    else {
		distV.setPolar(dimgap + dimtxt/2.0, angle-M_PI_2);
        textAngle = angle+M_PI;
    }

    // move text label:
    RS_Vector textPos;

    if (data.middleOfText.valid && !autoText) {
        textPos = data.middleOfText;
    } else {
        if (outsideArrow) {
            textPos.setPolar(length-textWidth/2.0-arrowSize, angle);
        } else {
            textPos.setPolar(length/2.0, angle);
        }
        textPos+=p1;
        // move text away from dimension line:
        textPos += distV;
        data.middleOfText = textPos;
    }

    text->rotate(RS_Vector(0.0,0.0), textAngle);
    text->move(textPos);

    text->setPen(RS_Pen(RS2::FlagInvalid));
    text->setLayer(NULL);
    addEntity(text);

    calculateBorders();
}
Пример #5
0
/**
 * Creates a vertex from the endpoint of the last element or 
 * sets the startpoint to the point 'v'.
 *
 * The very first vertex added is the starting point.
 * 
 * @param v vertex coordinate
 * @param bulge The bulge of the arc (see DXF documentation)
 * @param prepend true: Prepend instead of append at end
 *
 * @return Pointer to the entity that was created or NULL if this
 *         was the first vertex added.
 */
RS_Entity* RS_Polyline::createVertex(const RS_Vector& v, double bulge, bool prepend) {

    RS_Entity* entity=NULL;

    RS_DEBUG->print("RS_Polyline::createVertex: %f/%f to %f/%f bulge: %f",
                    data.endpoint.x, data.endpoint.y, v.x, v.y, bulge);

    // create line for the polyline:
    if (fabs(bulge)<RS_TOLERANCE) {
		if (prepend==false) {
        	entity = new RS_Line(this, RS_LineData(data.endpoint, v));
		}
		else {
        	entity = new RS_Line(this, RS_LineData(v, data.startpoint));
		}
        entity->setSelected(isSelected());
        entity->setPen(RS_Pen(RS2::FlagInvalid));
        entity->setLayer(NULL);
        //RS_EntityContainer::addEntity(entity);
        //data.endpoint = v;
    }

    // create arc for the polyline:
    else {
        bool reversed = (bulge<0.0);
        double alpha = atan(bulge)*4.0;

        double radius;
        RS_Vector center;
        RS_Vector middle;
        double dist;
        double angle;

		if (prepend==false) {
	        middle = (data.endpoint+v)/2.0;
    	    dist = data.endpoint.distanceTo(v)/2.0;
        	angle = data.endpoint.angleTo(v);
		}
		else {
	        middle = (data.startpoint+v)/2.0;
    	    dist = data.startpoint.distanceTo(v)/2.0;
        	angle = v.angleTo(data.startpoint);
		}

        // alpha can't be 0.0 at this point
        radius = fabs(dist / sin(alpha/2.0));

        double wu = fabs(RS_Math::pow(radius, 2.0) - RS_Math::pow(dist, 2.0));
        double h = sqrt(wu);

        if (bulge>0.0) {
            angle+=M_PI/2.0;
        } else {
            angle-=M_PI/2.0;
        }

        if (fabs(alpha)>M_PI) {
            h*=-1.0;
        }

        center.setPolar(h, angle);
        center+=middle;

		double a1;
		double a2;

		if (prepend==false) {
			a1 = center.angleTo(data.endpoint);
			a2 = center.angleTo(v);
		}
		else {
			a1 = center.angleTo(v);
			a2 = center.angleTo(data.startpoint);
		}

        RS_ArcData d(center, radius,
                     a1, a2,
                     reversed);

        entity = new RS_Arc(this, d);
        entity->setSelected(isSelected());
        entity->setPen(RS_Pen(RS2::FlagInvalid));
        entity->setLayer(NULL);
    }

    return entity;
}
Пример #6
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 NULL 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==NULL || l2==NULL ||
            l1->rtti()!=RS2::EntityLine || l2->rtti()!=RS2::EntityLine) {
        return NULL;
    }

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

    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 = NULL;

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

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

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

        RS_LineData d;
        RS_Vector v;

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

        RS_Line* newLine = new RS_Line(container, d);
        if (container!=NULL) {
            newLine->setLayerToActive();
            newLine->setPenToActive();
            container->addEntity(newLine);
        }
        if (document!=NULL && handleUndo) {
            document->addUndoable(newLine);
        }
        if (graphicView!=NULL) {
            graphicView->drawEntity(newLine);
        }
        if (ret==NULL) {
            ret = newLine;
        }
    }
    if (document!=NULL && handleUndo) {
        document->endUndoCycle();
    }

    return ret;
}
Пример #7
0
    /**
     * Creates a tangent between two circles or arcs.
     * Out of the 4 possible tangents, the one closest to
     * the given coordinate is returned.
     *
     * @param coord Coordinate to define which tangent we want (typically a
     *              mouse coordinate).
     * @param circle1 1st circle or arc entity.
     * @param circle2 2nd circle or arc entity.
     */
    RS_Line* RS_Creation::createTangent2(const RS_Vector& coord,
                                         RS_Entity* circle1,
                                         RS_Entity* circle2) {
        RS_Line* ret = NULL;
        RS_Vector circleCenter1;
        RS_Vector circleCenter2;
        double circleRadius1 = 0.0;
        double circleRadius2 = 0.0;

        // check given entities:
        if (circle1==NULL || circle2==NULL ||
                (circle1->rtti()!=RS2::EntityArc &&
                 circle1->rtti()!=RS2::EntityCircle) ||
                (circle2->rtti()!=RS2::EntityArc &&
                 circle2->rtti()!=RS2::EntityCircle) ) {

            return NULL;
        }

        if (circle1->rtti()==RS2::EntityCircle) {
            circleCenter1 = ((RS_Circle*)circle1)->getCenter();
            circleRadius1 = ((RS_Circle*)circle1)->getRadius();
        } else if (circle1->rtti()==RS2::EntityArc) {
            circleCenter1 = ((RS_Arc*)circle1)->getCenter();
            circleRadius1 = ((RS_Arc*)circle1)->getRadius();
        }

        if (circle2->rtti()==RS2::EntityCircle) {
            circleCenter2 = ((RS_Circle*)circle2)->getCenter();
            circleRadius2 = ((RS_Circle*)circle2)->getRadius();
        } else if (circle2->rtti()==RS2::EntityArc) {
            circleCenter2 = ((RS_Arc*)circle2)->getCenter();
            circleRadius2 = ((RS_Arc*)circle2)->getRadius();
        }

        // create all possible tangents:
        RS_Line* poss[4];
        for (int i=0; i<4; ++i) {
            poss[i] = NULL;
        }

        RS_LineData d;

        double angle1 = circleCenter1.angleTo(circleCenter2);
        double dist1 = circleCenter1.distanceTo(circleCenter2);

        if (dist1>1.0e-6) {
            // outer tangents:
            double dist2 = circleRadius2 - circleRadius1;
            if (dist1>dist2) {
                double angle2 = asin(dist2/dist1);
                double angt1 = angle1 + angle2 + M_PI/2.0;
                double angt2 = angle1 - angle2 - M_PI/2.0;
                RS_Vector offs1;
                RS_Vector offs2;

                offs1.setPolar(circleRadius1, angt1);
                offs2.setPolar(circleRadius2, angt1);

                d = RS_LineData(circleCenter1 + offs1,
                                circleCenter2 + offs2);
                poss[0] = new RS_Line(NULL, d);


                offs1.setPolar(circleRadius1, angt2);
                offs2.setPolar(circleRadius2, angt2);

                d = RS_LineData(circleCenter1 + offs1,
                                circleCenter2 + offs2);
                poss[1] = new RS_Line(NULL, d);
            }

            // inner tangents:
            double dist3 = circleRadius2 + circleRadius1;
            if (dist1>dist3) {
                double angle3 = asin(dist3/dist1);
                double angt3 = angle1 + angle3 + M_PI/2.0;
                double angt4 = angle1 - angle3 - M_PI/2.0;
                RS_Vector offs1;
                RS_Vector offs2;

                offs1.setPolar(circleRadius1, angt3);
                offs2.setPolar(circleRadius2, angt3);

                d = RS_LineData(circleCenter1 - offs1,
                                circleCenter2 + offs2);
                poss[2] = new RS_Line(NULL, d);


                offs1.setPolar(circleRadius1, angt4);
                offs2.setPolar(circleRadius2, angt4);

                d = RS_LineData(circleCenter1 - offs1,
                                circleCenter2 + offs2);
                poss[3] = new RS_Line(NULL, d);
            }

        }

        // find closest tangent:
        double minDist = RS_MAXDOUBLE;
        double dist;
        int idx = -1;
        for (int i=0; i<4; ++i) {
            if (poss[i]!=NULL) {
                dist = poss[i]->getDistanceToPoint(coord);
                if (dist<minDist) {
                    minDist = dist;
                    idx = i;
                }
            }
        }

        if (idx!=-1) {
            RS_LineData d = poss[idx]->getData();
            for (int i=0; i<4; ++i) {
                if (poss[i]!=NULL) {
                    delete poss[i];
                }
            }

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

            ret = new RS_Line(container, d);
            ret->setLayerToActive();
            ret->setPenToActive();
            if (container!=NULL) {
                container->addEntity(ret);
            }
            if (document!=NULL && handleUndo) {
                document->addUndoable(ret);
                document->endUndoCycle();
            }
            if (graphicView!=NULL) {
                graphicView->drawEntity(ret);
            }
        } else {
            ret = NULL;
        }

        return ret;
    }
void RS_ActionDrawLineRectangle::reset() {
    for (int i=0; i<4; ++i) {
        data[i] = RS_LineData(RS_Vector(false),
                              RS_Vector(false));
    }
}
Пример #9
0
double RS_ActionDrawPolyline::solveBulge(RS_Vector mouse) {

    double b(0.);
    bool suc;
    RS_Arc arc(NULL, RS_ArcData());
    RS_Line line(NULL,RS_LineData());
    double direction,direction2,delta;
    RS_AtomicEntity* lastentity;
    calculatedSegment=false;

    switch (Mode) {
//     case Line:
//        b=0.0;
//        break;
    case Tangential:
        if (polyline!=NULL) {
            lastentity = (RS_AtomicEntity*)polyline->lastEntity();
            direction = RS_Math::correctAngle(
                            lastentity->getDirection2()+M_PI);
            line.setStartpoint(point);
            line.setEndpoint(mouse);
            direction2=RS_Math::correctAngle(line.getDirection2()+M_PI);
            delta=direction2-direction;
            if( fabs(remainder(delta,M_PI))>RS_TOLERANCE_ANGLE ) {
                b=tan(delta/2);
                suc = arc.createFrom2PBulge(point,mouse,b);
                if (suc)
                    arc_data = arc.getData();
                else
                    b=0;
            }
            break;
//            if(delta<RS_TOLERANCE_ANGLE ||
//                (delta<M_PI+RS_TOLERANCE_ANGLE &&
//                delta>M_PI-RS_TOLERANCE_ANGLE))
//                b=0;
//            else{
//                b=tan((direction2-direction)/2);
//                suc = arc.createFrom2PBulge(point,mouse,b);
//                if (suc)
//                    arc_data = arc.getData();
//                else
//                    b=0;
//            }
        }
//        else
//            b=0;
//        break;
    case TanRad:
        if (polyline!=NULL) {
            lastentity = (RS_AtomicEntity*)polyline->lastEntity();
            direction = RS_Math::correctAngle(
                            lastentity->getDirection2()+M_PI);
            suc = arc.createFrom2PDirectionRadius(point, mouse,
                                                  direction,Radius);
            if (suc) {
                arc_data = arc.getData();
                b=arc.getBulge();
                calculatedEndpoint = arc.getEndpoint();
                calculatedSegment=true;

            }
//            else
//                b=0;
        }
//        else
//          b=0;
        break;
    /*     case TanAng:
            b=tan(Reversed*Angle*M_PI/720.0);
            break;
         case TanRadAng:
            b=tan(Reversed*Angle*M_PI/720.0);
            break;*/
    case Ang:
        b=tan(Reversed*Angle*M_PI/720.0);
        suc = arc.createFrom2PBulge(point,mouse,b);
        if (suc)
            arc_data = arc.getData();
        else
            b=0;
        break;
    default:
        break;
        /*     case RadAngEndp:
        b=tan(Reversed*Angle*M_PI/720.0);
        break;
        case RadAngCenp:
        b=tan(Reversed*Angle*M_PI/720.0);*/
    }
    return b;
}
Пример #10
0
/**
 * Creates a dimensioning line (line with one, two or no arrows and a text).
 *
 * @param forceAutoText Automatically reposition the text label.
 */
void RS_Dimension::updateCreateDimensionLine(const RS_Vector& p1,
        const RS_Vector& p2, bool arrow1, bool arrow2, bool forceAutoText) {

    // text height (DIMTXT)
    double dimtxt = getTextHeight();
    // text distance to line (DIMGAP)
    double dimgap = getDimensionLineGap();

    // length of dimension line:
    double distance = p1.distanceTo(p2);

    // do we have to put the arrows outside of the line?
    bool outsideArrows = (distance<getArrowSize()*2.5);

    // arrow angles:
    double arrowAngle1, arrowAngle2;

    // Create dimension line:
    RS_Line* dimensionLine = new RS_Line(this, RS_LineData(p1, p2));
    dimensionLine->setPen(RS_Pen(RS2::FlagInvalid));
    dimensionLine->setLayer(NULL);
    addEntity(dimensionLine);

    if (outsideArrows==false) {
        arrowAngle1 = dimensionLine->getAngle2();
        arrowAngle2 = dimensionLine->getAngle1();
    } else {
        arrowAngle1 = dimensionLine->getAngle1();
        arrowAngle2 = dimensionLine->getAngle2();

        // extend dimension line outside arrows
        RS_Vector dir;
        dir.setPolar(getArrowSize()*2, arrowAngle2);
        dimensionLine->setStartpoint(p1 + dir);
        dimensionLine->setEndpoint(p2 - dir);
    }
double dimtsz=getTickSize();
if(dimtsz < 0.01) {
    //display arrow
    // Arrows:
    RS_SolidData sd;
    RS_Solid* arrow;

    if (arrow1) {
        // arrow 1
        arrow = new RS_Solid(this, sd);
        arrow->shapeArrow(p1,
                          arrowAngle1,
                          getArrowSize());
        arrow->setPen(RS_Pen(RS2::FlagInvalid));
        arrow->setLayer(NULL);
        addEntity(arrow);
    }

    if (arrow2) {
        // arrow 2:
        arrow = new RS_Solid(this, sd);
        arrow->shapeArrow(p2,
                          arrowAngle2,
                          getArrowSize());
        arrow->setPen(RS_Pen(RS2::FlagInvalid));
        arrow->setLayer(NULL);
        addEntity(arrow);
    }
}else{
    //display ticks
    // Arrows:

    RS_Line* tick;
    RS_Vector tickVector;
    tickVector.setPolar(dimtsz,arrowAngle1 + M_PI*0.25); //tick is 45 degree away

    if (arrow1) {
        // tick 1
        tick = new RS_Line(this, p1-tickVector, p1+tickVector);
        tick->setPen(RS_Pen(RS2::FlagInvalid));
        tick->setLayer(NULL);
        addEntity(tick);
    }

    if (arrow2) {
        // tick 2:
        tick = new RS_Line(this, p2-tickVector, p2+tickVector);
        tick->setPen(RS_Pen(RS2::FlagInvalid));
        tick->setLayer(NULL);
        addEntity(tick);
    }
}
    // Text label:
    RS_MTextData textData;
    RS_Vector textPos;

        double dimAngle1 = dimensionLine->getAngle1();
        double textAngle;
        bool corrected=false;
        if (getAlignText())
            textAngle =0.0;
        else
            textAngle = RS_Math::makeAngleReadable(dimAngle1, true, &corrected);

    if (data.middleOfText.valid && !forceAutoText) {
        textPos = data.middleOfText;
    } else {
        textPos = dimensionLine->getMiddlePoint();

        if (!getAlignText()) {
            RS_Vector distV;

            // rotate text so it's readable from the bottom or right (ISO)
            // quadrant 1 & 4
            if (corrected) {
                distV.setPolar(dimgap + dimtxt/2.0, dimAngle1-M_PI/2.0);
            } else {
                distV.setPolar(dimgap + dimtxt/2.0, dimAngle1+M_PI/2.0);
            }

            // move text away from dimension line:
            textPos+=distV;
        }
        //// the next update should still be able to adjust this
        ////   auto text position. leave it invalid
                data.middleOfText = textPos;
    }

    textData = RS_MTextData(textPos,
                           dimtxt, 30.0,
                           RS_MTextData::VAMiddle,
                           RS_MTextData::HACenter,
                           RS_MTextData::LeftToRight,
                           RS_MTextData::Exact,
                           1.0,
                           getLabel(),
                           "standard",
                           textAngle);

    RS_MText* text = new RS_MText(this, textData);

    // move text to the side:
    RS_Vector distH;
    if (text->getUsedTextWidth()>distance) {
        distH.setPolar(text->getUsedTextWidth()/2.0
                       +distance/2.0+dimgap, textAngle);
        text->move(distH);
    }
    text->setPen(RS_Pen(RS2::FlagInvalid));
    text->setLayer(NULL);
    //horizontal text, split dimensionLine
    if (getAlignText()) {
        double w =text->getUsedTextWidth()/2+dimgap;
        double h = text->getUsedTextHeight()/2+dimgap;
        RS_Vector v1 = textPos - RS_Vector(w, h);
        RS_Vector v2 = textPos + RS_Vector(w, h);
        RS_Line l[] = {
            RS_Line(NULL, RS_LineData(v1, RS_Vector(v2.x, v1.y))),
            RS_Line(NULL, RS_LineData(RS_Vector(v2.x, v1.y), v2)),
            RS_Line(NULL, RS_LineData(v2, RS_Vector(v1.x, v2.y))),
            RS_Line(NULL, RS_LineData(RS_Vector(v1.x, v2.y), v1))
        };
        RS_VectorSolutions sol1, sol2;
        int inters= 0;
        do {
            sol1 = RS_Information::getIntersection(dimensionLine, &(l[inters++]), true);
        } while (!sol1.hasValid() && inters < 4);
        do {
            sol2 = RS_Information::getIntersection(dimensionLine, &(l[inters++]), true);
        } while (!sol2.hasValid() && inters < 4);
        //are text intersecting dimensionLine?
        if (sol1.hasValid() && sol2.hasValid()) {
            //yes, split dimension line
            RS_Line* dimensionLine2 = (RS_Line*)dimensionLine->clone();
            v1 = sol1.get(0);
            v2 = sol2.get(0);
            if (p1.distanceTo(v1) < p1.distanceTo(v2)) {
                dimensionLine->setEndpoint(v1);
                dimensionLine2->setStartpoint(v2);
            } else {
                dimensionLine->setEndpoint(v2);
                dimensionLine2->setStartpoint(v1);
            }
            addEntity(dimensionLine2);
        }
    }

    addEntity(text);
}
void RS_ActionDrawLineRectangle::preparePreview() {
    data[0] = RS_LineData(corner1, RS_Vector(corner2.x, corner1.y));
    data[1] = RS_LineData(RS_Vector(corner2.x, corner1.y), corner2);
    data[2] = RS_LineData(corner2, RS_Vector(corner1.x, corner2.y));
    data[3] = RS_LineData(RS_Vector(corner1.x, corner2.y), corner1);
}
Пример #12
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) {
                                    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) {
                                    sure = false;
                                }
                            }
                            // else: ray goes through the line


                                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++;
                            }
                        } else if (e->rtti()==RS2::EntityEllipse) {
                            RS_Ellipse* ellipse=static_cast<RS_Ellipse*>(e);
                            if(ellipse->isArc()){
                                if (p.distanceTo(ellipse->getStartpoint())<1.0e-4) {
                                    double dir = ellipse->getDirection1();
                                    if ((dir<M_PI && dir>=1.0e-5) ||
                                            ((dir>2*M_PI-1.0e-5 || dir<1.0e-5) &&
                                             ellipse->getCenter().y>p.y)) {
                                        counter++;
                                        sure = false;
                                    }
                                }
                                else if (p.distanceTo(ellipse->getEndpoint())<1.0e-4) {
                                    double dir = ellipse->getDirection2();
                                    if ((dir<M_PI && dir>=1.0e-5) ||
                                            ((dir>2*M_PI-1.0e-5 || dir<1.0e-5) &&
                                             ellipse->getCenter().y>p.y)) {
                                        counter++;
                                        sure = false;
                                    }
                                } else {
                                    counter++;
                                }
                            }else{
                                // 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);
}
Пример #13
0
/**
 * Updates the sub entities of this dimension. Called when the
 * text or the position, alignment, .. changes.
 *
 * @param autoText Automatically reposition the text label
 */
void RS_DimAligned::update(bool autoText) {

    RS_DEBUG->print("RS_DimAligned::update");

    clear();

        if (isUndone()) {
                return;
        }

    // general scale (DIMSCALE)
    double dimscale = getGeneralScale();
    // distance from entities (DIMEXO)
    double dimexo = getExtensionLineOffset()*dimscale;
    // definition line definition (DIMEXE)
    double dimexe = getExtensionLineExtension()*dimscale;
    // text height (DIMTXT)
    //double dimtxt = getTextHeight();
    // text distance to line (DIMGAP)
    //double dimgap = getDimensionLineGap();

    // Angle from extension endpoints towards dimension line
    double extAngle = edata.extensionPoint2.angleTo(data.definitionPoint);
    // extension lines length
    double extLength = edata.extensionPoint2.distanceTo(data.definitionPoint);

    RS_Vector v1, v2, e1;
    RS_LineData ld;
    RS_Line* line;

    v1.setPolar(dimexo, extAngle);
    v2.setPolar(dimexe, extAngle);
    e1.setPolar(1.0, extAngle);

    // Extension line 1:
    ld = RS_LineData(edata.extensionPoint1 + v1,
                     edata.extensionPoint1 + e1*extLength + v2);
    line = new RS_Line(this, ld);
    //line->setLayerToActive();
    //line->setPenToActive();
    line->setPen(RS_Pen(RS2::FlagInvalid));
    line->setLayer(NULL);
    addEntity(line);

    // Extension line 2:
    ld = RS_LineData(edata.extensionPoint2 + v1,
                     edata.extensionPoint2 + e1*extLength + v2);
    line = new RS_Line(this, ld);
    //line->setLayerToActive();
    //line->setPenToActive();
    line->setPen(RS_Pen(RS2::FlagInvalid));
    line->setLayer(NULL);
    addEntity(line);

    // Dimension line:
    updateCreateDimensionLine(edata.extensionPoint1 + e1*extLength,
                              edata.extensionPoint2 + e1*extLength,
                                                          true, true, autoText);

    calculateBorders();
}
Пример #14
0
/**
* Creates a tangent between two circles or arcs.
* Out of the 4 possible tangents, the one closest to
* the given coordinate is returned.
*
* @param coord Coordinate to define which tangent we want (typically a
*              mouse coordinate).
* @param circle1 1st circle or arc entity.
* @param circle2 2nd circle or arc entity.
*/
RS_Line* RS_Creation::createTangent2(const RS_Vector& coord,
                                     RS_Entity* circle1,
                                     RS_Entity* circle2) {
    RS_Line* ret = NULL;
    RS_Vector circleCenter1;
    RS_Vector circleCenter2;
    double circleRadius1 = 0.0;
    double circleRadius2 = 0.0;

    // check given entities:
    if (circle1==NULL || circle2==NULL ||
            ((circle1->rtti()!=RS2::EntityArc &&
              circle1->rtti()!=RS2::EntityEllipse &&
              circle1->rtti()!=RS2::EntityCircle) ||
             (circle2->rtti()!=RS2::EntityArc &&
              circle2->rtti()!=RS2::EntityEllipse &&
              circle2->rtti()!=RS2::EntityCircle) )) {

        return NULL;
    }

    QVector<RS_Line*> poss;
    //        for (int i=0; i<4; ++i) {
    //            poss[i] = NULL;
    //        }
    RS_LineData d;
    if( circle1->rtti() == RS2::EntityEllipse) {
        std::swap(circle1,circle2);//move Ellipse to the second place
    }
    circleCenter1=circle1->getCenter();
    circleRadius1=circle1->getRadius();
    circleCenter2=circle2->getCenter();
    circleRadius2=circle2->getRadius();
    if(circle2->rtti() != RS2::EntityEllipse) {
        //no ellipse

        // create all possible tangents:

        double angle1 = circleCenter1.angleTo(circleCenter2);
        double dist1 = circleCenter1.distanceTo(circleCenter2);

        if (dist1>1.0e-6) {
            // outer tangents:
            double dist2 = circleRadius2 - circleRadius1;
            if (dist1>dist2) {
                double angle2 = asin(dist2/dist1);
                double angt1 = angle1 + angle2 + M_PI/2.0;
                double angt2 = angle1 - angle2 - M_PI/2.0;
                RS_Vector offs1;
                RS_Vector offs2;

                offs1.setPolar(circleRadius1, angt1);
                offs2.setPolar(circleRadius2, angt1);

                d = RS_LineData(circleCenter1 + offs1,
                                circleCenter2 + offs2);
                poss.push_back( new RS_Line(NULL, d));


                offs1.setPolar(circleRadius1, angt2);
                offs2.setPolar(circleRadius2, angt2);

                d = RS_LineData(circleCenter1 + offs1,
                                circleCenter2 + offs2);
                poss.push_back( new RS_Line(NULL, d));
            }

            // inner tangents:
            double dist3 = circleRadius2 + circleRadius1;
            if (dist1>dist3) {
                double angle3 = asin(dist3/dist1);
                double angt3 = angle1 + angle3 + M_PI/2.0;
                double angt4 = angle1 - angle3 - M_PI/2.0;
                RS_Vector offs1;
                RS_Vector offs2;

                offs1.setPolar(circleRadius1, angt3);
                offs2.setPolar(circleRadius2, angt3);

                d = RS_LineData(circleCenter1 - offs1,
                                circleCenter2 + offs2);
                poss.push_back( new RS_Line(NULL, d));


                offs1.setPolar(circleRadius1, angt4);
                offs2.setPolar(circleRadius2, angt4);

                d = RS_LineData(circleCenter1 - offs1,
                                circleCenter2 + offs2);
                poss.push_back( new RS_Line(NULL, d));
            }

        }
    } else {
        //circle2 is Ellipse
        RS_Ellipse* e2=(RS_Ellipse*)circle2->clone();
//        RS_Ellipse* e2=new RS_Ellipse(NULL,RS_EllipseData(RS_Vector(4.,1.),RS_Vector(2.,0.),0.5,0.,0.,false));
//        RS_Ellipse  e3(NULL,RS_EllipseData(RS_Vector(4.,1.),RS_Vector(2.,0.),0.5,0.,0.,false));
//        RS_Ellipse* circle1=new RS_Ellipse(NULL,RS_EllipseData(RS_Vector(0.,0.),RS_Vector(1.,0.),1.,0.,0.,false));
        RS_Vector m0(circle1->getCenter());
//        std::cout<<"translation: "<<-m0<<std::endl;
        e2->move(-m0); //circle1 centered at origin

        double a,b;
        double a0(0.);
        if(circle1->rtti() != RS2::EntityEllipse) { //circle1 is either arc or circle
            a=fabs(circle1->getRadius());
            b=a;
            if(fabs(a)<RS_TOLERANCE) return NULL;
        } else { //circle1 is ellipse
            RS_Ellipse* e1=static_cast<RS_Ellipse*>(circle1);
            a0=e1->getAngle();
//            std::cout<<"rotation: "<<-a0<<std::endl;
            e2->rotate(-a0);//e1 major axis along x-axis
            a=e1->getMajorRadius();
            b=e1->getRatio()*a;
            if(fabs(a)<RS_TOLERANCE || fabs(b)<RS_TOLERANCE) return NULL;
        }
        RS_Vector factor1(1./a,1./b);
//        std::cout<<"scaling: factor1="<<factor1<<std::endl;
        e2->scale(RS_Vector(0.,0.),factor1);//circle1 is a unit circle
        factor1.set(a,b);
        double a2(e2->getAngle());
//        std::cout<<"rotation: a2="<<-a2<<std::endl;
        e2->rotate(-a2); //ellipse2 with major axis in x-axis direction
        a=e2->getMajorP().x;
        b=a*e2->getRatio();
        RS_Vector v(e2->getCenter());
//        std::cout<<"Center: (x,y)="<<v<<std::endl;


        std::vector<double> m(0,0.);
        m.push_back(1./(a*a)); //ma000
        m.push_back(1./(b*b)); //ma000
        m.push_back(v.y*v.y-1.); //ma100
        m.push_back(v.x*v.y); //ma101
        m.push_back(v.x*v.x-1.); //ma111
        m.push_back(2.*a*b*v.y); //mb10
        m.push_back(2.*a*b*v.x); //mb11
        m.push_back(a*a*b*b); //mc1

        auto&& vs0=RS_Math::simultaneousQuadraticSolver(m); //to hold solutions
        if (vs0.getNumber()<1) return NULL;
        for(int i=0; i<vs0.getNumber(); i++) {
//            std::cout<<"i="<<i<<"\n";
            RS_Vector vpec=vs0.get(i); //this holds ( a*sin(t), b*cos(t))
//            std::cout<<"solution "<<i<<" ="<<vpec<<std::endl;
            RS_Vector vpe2(e2->getCenter()+ RS_Vector(vpec.y/e2->getRatio(),vpec.x*e2->getRatio()));
            vpec.x *= -1.;//direction vector of tangent
            RS_Vector vpe1(vpe2 - vpec*(RS_Vector::dotP(vpec,vpe2)/vpec.squared()));
//            std::cout<<"vpe1.squared()="<<vpe1.squared()<<std::endl;
            RS_Line *l=new RS_Line(NULL,RS_LineData(vpe1,vpe2));
            l->rotate(a2);
            l->scale(factor1);
            l->rotate(a0);
            l->move(m0);
            poss.push_back(l);

        }
        delete e2;
        //debugging

    }
    // find closest tangent:
    if(poss.size()<1) return NULL;
    double minDist = RS_MAXDOUBLE;
    double dist;
    int idx = -1;
    for (int i=0; i<poss.size(); ++i) {
        if (poss[i]!=NULL) {
            poss[i]->getNearestPointOnEntity(coord,false,&dist);
//        std::cout<<poss.size()<<": i="<<i<<" dist="<<dist<<"\n";
            if (dist<minDist) {
                minDist = dist;
                idx = i;
            }
        }
    }
//idx=static_cast<int>(poss.size()*(random()/(double(1.0)+RAND_MAX)));
    if (idx!=-1) {
        RS_LineData d = poss[idx]->getData();
        for (int i=0; i<poss.size(); ++i) {
            if (poss[i]!=NULL) {
                delete poss[i];
            }
        }

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

        ret = new RS_Line(container, d);
        ret->setLayerToActive();
        ret->setPenToActive();
        if (container!=NULL) {
            container->addEntity(ret);
        }
        if (document!=NULL && handleUndo) {
            document->addUndoable(ret);
            document->endUndoCycle();
        }
        if (graphicView!=NULL) {
            graphicView->drawEntity(ret);
        }
    } else {
        ret = NULL;
    }

    return ret;
}
/**
 * Updates the sub entities of this dimension. Called when the 
 * dimension or the position, alignment, .. changes.
 *
 * @param autoText Automatically reposition the text label
 */
void RS_DimAngular::update(bool /*autoText*/) {

    RS_DEBUG->print("RS_DimAngular::update");

    clear();
	
	if (isUndone()) {
		return;
	}

    // distance from entities (DIMEXO)
    double dimexo = getExtensionLineOffset();
    // extension line extension (DIMEXE)
    double dimexe = getExtensionLineExtension();
    // text height (DIMTXT)
    double dimtxt = getTextHeight();
    // text distance to line (DIMGAP)
    double dimgap = getDimensionLineGap();

    // find out center:
    RS_Vector center = getCenter();

    if (!center.valid) {
        return;
    }

    double ang1 = 0.0;
    double ang2 = 0.0;
    bool reversed = false;
    RS_Vector p1;
    RS_Vector p2;

    getAngles(ang1, ang2, reversed, p1, p2);

    double rad = edata.definitionPoint4.distanceTo(center);

    RS_Line* line;
    RS_Vector dir;
    double len;
    double dist;

    // 1st extension line:
    dist = center.distanceTo(p1);
    len = rad - dist + dimexe;
    dir.setPolar(1.0, ang1);
    line = new RS_Line(this,
                       RS_LineData(center + dir*dist + dir*dimexo,
                                   center + dir*dist + dir*len));
    line->setPen(RS_Pen(RS2::FlagInvalid));
    line->setLayer(NULL);
    addEntity(line);

    // 2nd extension line:
    dist = center.distanceTo(p2);
    len = rad - dist + dimexe;
    dir.setPolar(1.0, ang2);
    line = new RS_Line(this,
                       RS_LineData(center + dir*dist + dir*dimexo,
                                   center + dir*dist + dir*len));
    line->setPen(RS_Pen(RS2::FlagInvalid));
    line->setLayer(NULL);
    addEntity(line);

    // Create dimension line (arc):
    RS_Arc* arc = new RS_Arc(this,
                             RS_ArcData(center,
                                        rad, ang1, ang2, reversed));
    arc->setPen(RS_Pen(RS2::FlagInvalid));
    arc->setLayer(NULL);
    addEntity(arc);

    // length of dimension arc:
    double distance = arc->getLength();

    // do we have to put the arrows outside of the arc?
    bool outsideArrows = (distance<getArrowSize()*2);

    // arrow angles:
    double arrowAngle1, arrowAngle2;
    double arrowAng;
	if (rad>1.0e-6) {
		arrowAng = getArrowSize() / rad;
	}
	else {
		arrowAng = 0.0;
	}
    RS_Vector v1, v2;
    if (!arc->isReversed()) {
        v1.setPolar(rad, arc->getAngle1()+arrowAng);
    } else {
        v1.setPolar(rad, arc->getAngle1()-arrowAng);
    }
    v1+=arc->getCenter();
    arrowAngle1 = arc->getStartpoint().angleTo(v1);


    if (!arc->isReversed()) {
        v2.setPolar(rad, arc->getAngle2()-arrowAng);
    } else {
        v2.setPolar(rad, arc->getAngle2()+arrowAng);
    }
    v2+=arc->getCenter();
    arrowAngle2 = arc->getEndpoint().angleTo(v2);

    if (!outsideArrows) {
        arrowAngle1 = arrowAngle1+M_PI;
        arrowAngle2 = arrowAngle2+M_PI;
    }

    // Arrows:
    RS_SolidData sd;
    RS_Solid* arrow;

    // arrow 1
    arrow = new RS_Solid(this, sd);
    arrow->shapeArrow(arc->getStartpoint(),
                      arrowAngle1,
                      getArrowSize());
    arrow->setPen(RS_Pen(RS2::FlagInvalid));
    arrow->setLayer(NULL);
    addEntity(arrow);

    // arrow 2:
    arrow = new RS_Solid(this, sd);
    arrow->shapeArrow(arc->getEndpoint(),
                      arrowAngle2,
                      getArrowSize());
    arrow->setPen(RS_Pen(RS2::FlagInvalid));
    arrow->setLayer(NULL);
    addEntity(arrow);


    // text label:
    RS_TextData textData;
    RS_Vector textPos = arc->getMiddlepoint();

    RS_Vector distV;
    double textAngle;
    double dimAngle1 = textPos.angleTo(arc->getCenter())-M_PI/2.0;

    // rotate text so it's readable from the bottom or right (ISO)
    // quadrant 1 & 4
    if (dimAngle1>M_PI/2.0*3.0+0.001 ||
            dimAngle1<M_PI/2.0+0.001) {

        distV.setPolar(dimgap, dimAngle1+M_PI/2.0);
        textAngle = dimAngle1;
    }
    // quadrant 2 & 3
    else {
        distV.setPolar(dimgap, dimAngle1-M_PI/2.0);
        textAngle = dimAngle1+M_PI;
    }

    // move text away from dimension line:
    textPos+=distV;

    textData = RS_TextData(textPos,
                           dimtxt, 30.0,
                           RS2::VAlignBottom,
                           RS2::HAlignCenter,
                           RS2::LeftToRight,
                           RS2::Exact,
                           1.0,
                           getLabel(),
                           "standard",
                           textAngle);

    RS_Text* text = new RS_Text(this, textData);

    // move text to the side:
    text->setPen(RS_Pen(RS2::FlagInvalid));
    text->setLayer(NULL);
    addEntity(text);

    calculateBorders();
}
Пример #16
0
/**
 * Selects all circles (and arcs min. 3/4 circle) with same diameter and same layer,
 * in a window (v1, v2)
 * mosty used with CAM bores 
 *
 * @param e  Must be an circle or arc (min. 3/4 circle)
 */
void RS_Selection::selectCircles(RS_Entity* e, RS_Vector v1, RS_Vector v2 /*, bool inside=true */ ) 
{
   if (e==NULL) 
     return;
   
   if (!e->isAtomic()) 
     return;

   e->toggleSelected(); 
   
   // bool cross = v2.y > v1.y;
   
   bool cross = v1.x > v2.x;
   
   bool select = !e->isSelected();
   RS_AtomicEntity* ae = (RS_AtomicEntity*)e;
   double r_clicked = 0;
   RS_Layer* layer_clicked = 0;
   

   if (graphicView!=NULL) 
     graphicView->drawEntity(e);
   
   if (ae->rtti()==RS2::EntityArc || ae->rtti()==RS2::EntityCircle)
     {
	r_clicked = ae->getRadius();
	
	if (ae->rtti()==RS2::EntityArc)
	  if(ae->getAngleLength() < 4.66)   /* ca. 267 grad (knapp 3/4 kreis) */
	    {
	       r_clicked = 0;
	       RS_DIALOGFACTORY->commandMessage("selected arc has AngleLength < 4.66");
	    }
	
	layer_clicked = ae->getLayer();
     }   
   
   for (RS_Entity* en=container->firstEntity(); en!=NULL; en=container->nextEntity()) 
     {
	int included = 0;
	
	if (en!=NULL && en->isVisible() && 
	    en->isAtomic() && en->isSelected()!=select && 
	    (en->rtti()==RS2::EntityArc || en->rtti()==RS2::EntityCircle) &&

	    (en->getLayer()==NULL || en->getLayer()->isLocked()==false)) 
	  {
	     ae = (RS_AtomicEntity*)en;
	     
 
	     if(en->isInWindow(v1, v2))
	       included++;
	     
	     if (cross == true)
	       {
		 RS_Line l[] =
		   {
                        RS_Line(NULL, RS_LineData(v1, RS_Vector(v2.x, v1.y))),
                        RS_Line(NULL, RS_LineData(RS_Vector(v2.x, v1.y), v2)),
                        RS_Line(NULL, RS_LineData(v2, RS_Vector(v1.x, v2.y))),
                        RS_Line(NULL, RS_LineData(RS_Vector(v1.x, v2.y), v1))
		   };
                RS_VectorSolutions sol;

                if (ae->isContainer()) 
		    continue;
                 else
		    {
		       for (int i=0; i<4; ++i) 
			 {
			    sol = RS_Information::getIntersection(ae, &l[i], true);
			    if (sol.hasValid())
			      {
				 included++;
				 break;
			      }
			 }
		    }
	       }
	     
	     // -----------------------
	     
	     if(included)
	       {
		  
		  double rc = ae->getRadius();
		  
		  double rdiff = fabs (rc - r_clicked);
		  
		  if ((r_clicked > 0.000003)  &&  (0.000003 > rdiff) && (ae->getLayer() == layer_clicked))
		    {
		       if (graphicView!=NULL)
			 {
			    graphicView->deleteEntity(ae);
			 }
		       
		       ae->setSelected(select);
		       
		       if (graphicView!=NULL) 
			 {
			    graphicView->drawEntity(ae);
			 }
		    }
	       }
	  }
     }
   //std::cerr << "ende in  rs_selection.cpp \n";
}
Пример #17
0
/**
 * Creates a line parallel to the given line e.
 * Out of the 2 possible parallels, the one closest to
 * the given coordinate is returned.
 *
 * @param coord Coordinate to define which parallel we want (typically a
 *              mouse coordinate).
 * @param distance Distance of the parallel.
 * @param number Number of parallels.
 * @param e Original entity.
 *
 * @return Pointer to the first created parallel or NULL if no
 *    parallel has been created.
 */
RS_Line* RS_Creation::createParallelLine(const RS_Vector& coord,
        double distance, int number,
        RS_Line* e) {

    if (e==NULL) {
        return NULL;
    }

    double ang = e->getAngle1() + M_PI/2.0;
    RS_Vector p1, p2;
    RS_LineData parallelData;
    RS_Line* ret = NULL;

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

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

        // calculate 1st parallel:
        p1.setPolar(distance*num, ang);
        p1 += e->getStartpoint();
        p2.setPolar(distance*num, ang);
        p2 += e->getEndpoint();
        RS_Line parallel1(NULL, RS_LineData(p1, p2));

        // calculate 2nd parallel:
        p1.setPolar(distance*num, ang+M_PI);
        p1 += e->getStartpoint();
        p2.setPolar(distance*num, ang+M_PI);
        p2 += e->getEndpoint();
        RS_Line parallel2(NULL, RS_LineData(p1, p2));

        double dist1 = parallel1.getDistanceToPoint(coord);
        double dist2 = parallel2.getDistanceToPoint(coord);
        double minDist = std::min(dist1, dist2);

        if (minDist<RS_MAXDOUBLE) {
            if (dist1<dist2) {
                parallelData = parallel1.getData();
            } else {
                parallelData = parallel2.getData();
            }


            RS_Line* newLine = new RS_Line(container, parallelData);
            newLine->setLayerToActive();
            newLine->setPenToActive();
            if (ret==NULL) {
                ret = newLine;
            }
            if (container!=NULL) {
                container->addEntity(newLine);
            }
            if (document!=NULL && handleUndo) {
                document->addUndoable(newLine);
                //document->endUndoCycle();
            }
            if (graphicView!=NULL) {
                graphicView->drawEntity(newLine);
            }
        }
    }

    if (document!=NULL && handleUndo) {
        document->endUndoCycle();
    }

    return ret;
}
Пример #18
0
/*RS_EntityContainer* parent,
                 const RS_LineData& d*/
Plugin_Entity::Plugin_Entity(RS_EntityContainer* parent, enum DPI::ETYPE type){
    hasContainer = false;
    entity = NULL;
    switch (type) {
    case DPI::POINT:
        entity = new RS_Point(parent, RS_PointData(RS_Vector(0,0)));
        break;
    case DPI::LINE:
        entity = new RS_Line(parent, RS_LineData());
        break;
/*    case DPI::CONSTRUCTIONLINE:
        entity = new RS_ConstructionLine();
        break;*/
    case DPI::CIRCLE:
        entity = new RS_Circle(parent, RS_CircleData());
        break;
    case DPI::ARC:
        entity = new RS_Arc(parent, RS_ArcData());
        break;
    case DPI::ELLIPSE:
        entity = new RS_Ellipse(parent, RS_EllipseData(RS_Vector(0,0), RS_Vector(0,0),0.0,0.0,0.0,false));
        break;
    case DPI::IMAGE:
        entity = new RS_Image(parent, RS_ImageData());
        break;
/*    case DPI::OVERLAYBOX:
        entity = new RS_OverlayBox();
        break;
    case DPI::SOLID:
        entity = new RS_Solid();
        break;*/
    case DPI::TEXT:
        entity = new RS_Text(parent, RS_TextData());
        break;
/*    case DPI::INSERT:
        entity = new RS_Insert();
        break;*/
    case DPI::POLYLINE:
        entity = new RS_Polyline(parent, RS_PolylineData());
        break;
/*    case DPI::SPLINE:
        entity = new RS_Spline();
        break;
    case DPI::HATCH:
        entity = new RS_Hatch();
        break;
    case DPI::DIMLEADER:
        entity = new RS_Leader();
        break;
    case DPI::DIMALIGNED:
        entity = new RS_DimAligned();
        break;
    case DPI::DIMLINEAR:
        entity = new RS_DimLinear();
        break;
    case DPI::DIMRADIAL:
        entity = new RS_DimRadial();
        break;
    case DPI::DIMDIAMETRIC:
        entity = new RS_DimDiametric();
        break;
    case DPI::DIMANGULAR:
        entity = new RS_DimAngular();
        break;*/
    default:
        break;
    }
}
Пример #19
0
    /**
     * Creates a tangent between a given point and a circle or arc.
     * Out of the 2 possible tangents, the one closest to
     * the given coordinate is returned.
     *
     * @param coord Coordinate to define which tangent we want (typically a
     *              mouse coordinate).
     * @param point Point.
     * @param circle Circle, arc or ellipse entity.
     */
    RS_Line* RS_Creation::createTangent1(const RS_Vector& coord,
                                         const RS_Vector& point,
                                         RS_Entity* circle) {
        RS_Line* ret = NULL;
        RS_Vector circleCenter;

        // check given entities:
        if (circle==NULL || !point.valid ||
                (circle->rtti()!=RS2::EntityArc && circle->rtti()!=RS2::EntityCircle
                 && circle->rtti()!=RS2::EntityEllipse)) {

            return NULL;
        }

        if (circle->rtti()==RS2::EntityCircle) {
            circleCenter = ((RS_Circle*)circle)->getCenter();
        } else if (circle->rtti()==RS2::EntityArc) {
            circleCenter = ((RS_Arc*)circle)->getCenter();
        } else if (circle->rtti()==RS2::EntityEllipse) {
            circleCenter = ((RS_Ellipse*)circle)->getCenter();
        }

        // the two tangent points:
        RS_VectorSolutions sol;

        // calculate tangent points for arcs / circles:
        if (circle->rtti()!=RS2::EntityEllipse) {
            // create temp. thales circle:
            RS_Vector tCenter = (point + circleCenter)/2.0;
            double tRadius = point.distanceTo(tCenter);

            RS_Circle tmp(NULL, RS_CircleData(tCenter, tRadius));

            // get the two intersection points which are the tangent points:
            sol = RS_Information::getIntersection(&tmp, circle, false);
        }

        // calculate tangent points for ellipses:
        else {
            RS_Ellipse* el = (RS_Ellipse*)circle;
            //sol.alloc(2);
            //sol.set(0, circleCenter);
            //sol.set(1, circleCenter);


            double a = el->getMajorRadius();     // the length of the major axis / 2
            double b = el->getMinorRadius();     // the length of the minor axis / 2

            // rotate and move point:
            RS_Vector point2 = point;
            point2.move(-el->getCenter());
            point2.rotate(-el->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);
            yt1 = (t - bf) / (af * 2.0);
            xt1 = e - d * yt1;
            yt2 = (-t - bf) / (af * 2.0);
            xt2 = e - d * yt2;

            RS_Vector s1 = RS_Vector(xt1, yt1);
            RS_Vector s2 = RS_Vector(xt2, yt2);

            s1.rotate(el->getAngle());
            s1.move(el->getCenter());

            s2.rotate(el->getAngle());
            s2.move(el->getCenter());

            sol.push_back(s1);
            sol.push_back(s2);


        }

        if (sol.getNumber() < 2 ) {
                return NULL;
        }
        if (!sol.get(0).valid || !sol.get(1).valid) {
            return NULL;
        }

        // create all possible tangents:
        RS_Line* poss[2];

        RS_LineData d;

        d = RS_LineData(sol.get(0), point);
        poss[0] = new RS_Line(NULL, d);
        d = RS_LineData(sol.get(1), point);
        poss[1] = new RS_Line(NULL, d);

        // find closest tangent:
        double minDist = RS_MAXDOUBLE;
        double dist;
        int idx = -1;
        for (int i=0; i<2; ++i) {
            dist = poss[i]->getDistanceToPoint(coord);
            if (dist<minDist) {
                minDist = dist;
                idx = i;
            }
        }

        // create the closest tangent:
        if (idx!=-1) {
            RS_LineData d = poss[idx]->getData();

            for (int i=0; i<2; ++i) {
                delete poss[i];
            }

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

            ret = new RS_Line(container, d);
            ret->setLayerToActive();
            ret->setPenToActive();
            if (container!=NULL) {
                container->addEntity(ret);
            }
            if (document!=NULL && handleUndo) {
                document->addUndoable(ret);
                document->endUndoCycle();
            }
            if (graphicView!=NULL) {
                graphicView->drawEntity(ret);
            }
        } else {
            ret = NULL;
        }

        return ret;
    }
Пример #20
0
bool RS_Solid::isInCrossWindow(const RS_Vector& v1,const RS_Vector& v2)const {
//    bool sol = false;
    RS_Vector vBL, vTR;
    RS_VectorSolutions sol;
//sort imput vectors to BottomLeft & TopRight
    if (v1.x<v2.x) {
        vBL.x = v1.x;
        vTR.x = v2.x;
    } else {
        vBL.x = v2.x;
        vTR.x = v1.x;
    }
    if (v1.y<v2.y) {
        vBL.y = v1.y;
        vTR.y = v2.y;
    } else {
        vBL.y = v2.y;
        vTR.y = v1.y;
    }
    //Check if is out of window
    if ( getMin().x > vTR.x || getMax().x < vBL.x
           || getMin().y > vTR.y || getMax().y < vBL.y) {
        return false;
    }
	std::vector<RS_Line> l;
	l.push_back(RS_Line(nullptr, RS_LineData(data.corner[0], data.corner[1])));
	l.push_back(RS_Line(nullptr, RS_LineData(data.corner[1], data.corner[2])));
    if (data.corner[3].valid) {
		l.push_back(RS_Line(nullptr, RS_LineData(data.corner[2], data.corner[3])));
		l.push_back(RS_Line(nullptr, RS_LineData(data.corner[3], data.corner[0])));
    } else {
		l.push_back(RS_Line(nullptr, RS_LineData(data.corner[2], data.corner[0])));
    }
    //Find crossing edge
    if (getMax().x > vBL.x && getMin().x < vBL.x) {//left
		RS_Line edge = RS_Line(nullptr, RS_LineData(vBL, RS_Vector(vBL.x, vTR.y)));
		for(auto const& l0: l) {
			sol = RS_Information::getIntersection(&edge, &l0, true);
            if (sol.hasValid()) {
                return true;
            }
        }
    }
    if (getMax().x > vTR.x && getMin().x < vTR.x) {//right
		RS_Line edge = RS_Line(nullptr, RS_LineData(RS_Vector(vTR.x, vBL.y), vTR));
		for(auto const& l0: l) {
			sol = RS_Information::getIntersection(&edge, &l0, true);
            if (sol.hasValid()) {
                return true;
            }
        }
    }
    if (getMax().y > vBL.y && getMin().y < vBL.y) {//bottom
		RS_Line edge = RS_Line(nullptr, RS_LineData(vBL, RS_Vector(vTR.x, vBL.y)));
		for(auto const& l0: l) {
			sol = RS_Information::getIntersection(&edge, &l0, true);
            if (sol.hasValid()) {
                return true;
            }
        }
    }
    if(getMax().y > vTR.y && getMin().y < vTR.y) {//top
		RS_Line edge = RS_Line(nullptr, RS_LineData(RS_Vector(vBL.x, vTR.y), vTR));
		for(auto const& l0: l) {
			sol = RS_Information::getIntersection(&edge, &l0, true);
            if (sol.hasValid()) {
                return true;
            }
        }
    }
    return false;
}
Пример #21
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());

    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;
                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");
        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 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");
        return;
    }

    // avoid huge memory consumption:
    else if (cSize.x/pSize.x>100 || cSize.y/pSize.y>100) {
        RS_DEBUG->print("RS_Hatch::update: contour size too large or pattern size too small");
        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) - 1;
    f = copy->getMax().y/pat->getSize().y;
    py2 = (int)ceil(f) - 1;

    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->rotate(RS_Vector(0.0,0.0), data.angle);
                RS_Vector v1, v2;
                v1.setPolar(px*pSize.x, data.angle);
                v2.setPolar(py*pSize.y, data.angle+M_PI/2.0);
                te->move(v1+v2);
                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;

        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");
}
Пример #22
0
bool RS_ActionDrawCircleTan3::getData(){
	if(getStatus() != SetCircle3) return false;
	//find the nearest circle
	size_t i=0;
	size_t const countLines=std::count_if(circles.begin(), circles.end(), [](RS_AtomicEntity* e)->bool
	{
			return e->rtti()==RS2::EntityLine;
});

	for(;i<circles.size();++i)
		if(circles[i]->rtti() == RS2::EntityLine) break;
	candidates.clear();
	size_t i1=(i+1)%3;
	size_t i2=(i+2)%3;
	if(i<circles.size() && circles[i]->rtti() == RS2::EntityLine){
		//one or more lines

		LC_Quadratic lc0(circles[i],circles[i1],false);
		LC_Quadratic lc1;
		RS_VectorSolutions sol;
		//detect degenerate case two circles with the same radius
		switch(countLines){
		default:
		case 0:
			//this should not happen
			assert(false);
		case 1:
			//1 line, two circles
		{
			for(unsigned k=0; k<4; ++k){
				//loop through all mirroring cases
				lc1=LC_Quadratic(circles[i],circles[i1], k & 1u);
				LC_Quadratic lc2=LC_Quadratic(circles[i],circles[i2], k & 2u);
				sol.appendTo(LC_Quadratic::getIntersection(lc1,lc2));
			}

		}
			break;
		case 2:
			//2 lines, one circle
		{
			if(circles[i2]->rtti()==RS2::EntityLine){
				std::swap(i1, i2);
			}
			//i2 is circle

			for(unsigned k=0; k<4; ++k){
				//loop through all mirroring cases
				lc1=LC_Quadratic(circles[i2],circles[i], k & 1u);
				LC_Quadratic lc2=LC_Quadratic(circles[i2],circles[i1], k & 2u);
				sol.appendTo(LC_Quadratic::getIntersection(lc1,lc2));
			}
		}
			break;
		case 3:
			//3 lines
		{
			lc0=circles[i]->getQuadratic();
			lc1=circles[i1]->getQuadratic();
			auto lc2=circles[i2]->getQuadratic();
			//attempt to have intersections (lc0, lc1), (lc0, lc2)
			auto sol1=LC_Quadratic::getIntersection(lc0,lc1);
			if(sol1.size()<1) {
				std::swap(lc0, lc2);
				std::swap(i, i2);
			}
			sol1=LC_Quadratic::getIntersection(lc0,lc2);
			if(sol1.size()<1) {
				std::swap(lc0, lc1);
				std::swap(i, i1);
			}

			RS_Line* line0=static_cast<RS_Line*>(circles[i]);
			RS_Line* line1=static_cast<RS_Line*>(circles[i1]);
			RS_Line* line2=static_cast<RS_Line*>(circles[i2]);
			lc0=line0->getQuadratic();
			lc1=line1->getQuadratic();
			lc2=line2->getQuadratic();
			//intersection 0, 1
			sol1=LC_Quadratic::getIntersection(lc0,lc1);
			if(!sol1.size()) {
				return false;
			}
			RS_Vector const v1=sol1.at(0);
			double angle1=0.5*(line0->getAngle1()+line1->getAngle1());

			//intersection 0, 2
			sol1=LC_Quadratic::getIntersection(lc0,lc2);
			double angle2;
			if(sol1.size()<1) {
				return false;
			}
			angle2=0.5*(line0->getAngle1()+line2->getAngle1());
			RS_Vector const& v2=sol1.at(0);
			//two bisector lines per intersection
			for(unsigned j=0; j<2; ++j){

                RS_Line l1(nullptr, RS_LineData(v1, v1+RS_Vector(angle1)));
				for(unsigned j1=0; j1<2; ++j1){
                    RS_Line l2(nullptr, RS_LineData(v2, v2+RS_Vector(angle2)));
					sol.appendTo(RS_Information::getIntersectionLineLine(&l1, &l2));
					angle2 += M_PI_2;
				}
				angle1 += M_PI_2;
			}
		}
		}

		double d;

		//line passes circle center, need a second parabola as the image of the line
		for(int j=1;j<=2;j++){
			if(circles[(i+j)%3]->rtti() == RS2::EntityCircle){
				circles[i]->getNearestPointOnEntity(circles[(i+j)%3]->getCenter(),
						false,&d);
				if(d<RS_TOLERANCE) {
					LC_Quadratic lc2(circles[i],circles[(i+j)%3], true);
					sol.appendTo(LC_Quadratic::getIntersection(lc2,lc1));
				}
			}
		}

		//clean up duplicate and invalid
		RS_VectorSolutions sol1;
		for(const RS_Vector& vp: sol){
			if(vp.magnitude()>RS_MAXDOUBLE) continue;
			if(sol1.size() && sol1.getClosestDistance(vp)<RS_TOLERANCE) continue;
			sol1.push_back(vp);
		}

		for(auto const& v: sol1){
			circles[i]->getNearestPointOnEntity(v,false,&d);
			std::shared_ptr<RS_CircleData> data(new RS_CircleData(v,d));
			if(circles[(i+1)%3]->isTangent(*data)==false) continue;
			if(circles[(i+2)%3]->isTangent(*data)==false) continue;
			candidates.push_back(data);
		}

	}else{
        RS_Circle c(nullptr,*cData);
		auto solutions=c.createTan3(circles);
		candidates.clear();
		for(const RS_Circle& s: solutions){
			candidates.push_back(std::make_shared<RS_CircleData>(s.getData()));
		}
	}
	valid = ( candidates.size() >0);
	return valid;
}