void RS_ActionDrawEllipseAxis::trigger() {
    RS_PreviewActionInterface::trigger();

    RS_EllipseData ellipseData(center, major,
                               ratio,
                               angle1, angle2,
                               false);
    RS_Ellipse* ellipse = new RS_Ellipse(container, ellipseData);
    ellipse->setLayerToActive();
    ellipse->setPenToActive();

    container->addEntity(ellipse);

    // upd. undo list:
    if (document!=NULL) {
        document->startUndoCycle();
        document->addUndoable(ellipse);
        document->endUndoCycle();
    }

    RS_Vector rz = graphicView->getRelativeZero();
    graphicView->redraw(RS2::RedrawDrawing);
    graphicView->moveRelativeZero(rz);
    drawSnapper();

    setStatus(SetCenter);

    RS_DEBUG->print("RS_ActionDrawEllipseAxis::trigger():"
                    " entity added: %d", ellipse->getId());
}
void RS_ActionDrawEllipseAxis::trigger() {
    RS_PreviewActionInterface::trigger();

	RS_Ellipse* ellipse = new RS_Ellipse{container,
	{pPoints->center, pPoints->m_vMajorP, pPoints->ratio,
			pPoints->angle1, pPoints->angle2, false}
};
	if (pPoints->ratio > 1.){
        ellipse->switchMajorMinor();
    }
    ellipse->setLayerToActive();
    ellipse->setPenToActive();

    container->addEntity(ellipse);

    // upd. undo list:
    if (document) {
        document->startUndoCycle();
        document->addUndoable(ellipse);
        document->endUndoCycle();
    }

    RS_Vector rz = graphicView->getRelativeZero();
    graphicView->redraw(RS2::RedrawDrawing);
    graphicView->moveRelativeZero(rz);
    drawSnapper();

    setStatus(SetCenter);

    RS_DEBUG->print("RS_ActionDrawEllipseAxis::trigger():"
                    " entity added: %d", ellipse->getId());
}
void RS_ActionDrawEllipseFociPoint::trigger() {
    RS_PreviewActionInterface::trigger();


    RS_EllipseData ed(center,
                      major*d,
                      sqrt(d*d-c*c)/d,
                      0., 0.,false);
    RS_Ellipse* ellipse = new RS_Ellipse(container, ed);
    ellipse->setLayerToActive();
    ellipse->setPenToActive();

    container->addEntity(ellipse);

    // upd. undo list:
    if (document!=NULL) {
        document->startUndoCycle();
        document->addUndoable(ellipse);
        document->endUndoCycle();
    }

//    RS_Vector rz = graphicView->getRelativeZero();
    graphicView->moveRelativeZero(ellipse->getCenter());
    graphicView->redraw(RS2::RedrawDrawing);
    drawSnapper();

    setStatus(SetFocus1);

    RS_DEBUG->print("RS_ActionDrawEllipseFociPoint::trigger():"
                    " entity added: %d", ellipse->getId());
}
Beispiel #4
0
void DL_Jww::CreateEnko(DL_CreationInterface* creationInterface, CDataEnko& DEnko)
{
	string lName = HEX[DEnko.m_nGLayer > ArraySize(HEX)-1 ? ArraySize(HEX)-1: DEnko.m_nGLayer] + "-" +
													HEX[DEnko.m_nLayer > ArraySize(HEX)-1 ? ArraySize(HEX)-1: DEnko.m_nLayer];

	// add layer
	creationInterface->addLayer(DL_LayerData(lName,0));

	int width;
	if(DEnko.m_nPenWidth > 26)
		width = 0;
	else
		width = DEnko.m_nPenWidth;
	int color = colTable[DEnko.m_nPenColor > ArraySize(colTable)-1 ? ArraySize(colTable)-1 : DEnko.m_nPenColor];
	attrib = DL_Attributes(values[8],	  // layer
			       color,	      // color
			       width,	      // width
			       lTable[DEnko.m_nPenStyle > ArraySize(lTable)-1 ? ArraySize(lTable)-1 : DEnko.m_nPenStyle]);	  // linetype
	creationInterface->setAttributes(attrib);

	creationInterface->setExtrusion(0.0, 0.0, 1.0, 0.0 );

	double angle1, angle2;
	//正円
	if(DEnko.m_bZenEnFlg){
		if(DEnko.m_dHenpeiRitsu == 1.0){
			DL_CircleData d(DEnko.m_start.x, DEnko.m_start.y, 0.0, DEnko.m_dHankei);
			creationInterface->addCircle(d);
		}else{
			double angle1, angle2;
			if(DEnko.m_radEnkoKaku > 0.0){
				angle1 = DEnko.m_radKaishiKaku;
				angle2 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku;
			}else{
				angle1 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku;
				angle2 = DEnko.m_radKaishiKaku;
			}
			angle1 = angle1 - floor(angle1 / (M_PI * 2.0)) * M_PI * 2.0;
			angle2 = angle2 - floor(angle2 / (M_PI * 2.0)) * M_PI * 2.0;
			if( angle2 <= angle1 )
				angle1 = angle1 - M_PI * 2.0;
			//楕円
			DL_EllipseData d(DEnko.m_start.x, DEnko.m_start.y, 0.0,
							DEnko.m_dHankei * cos(DEnko.m_radKatamukiKaku), DEnko.m_dHankei * sin(DEnko.m_radKatamukiKaku), 0.0,
							DEnko.m_dHenpeiRitsu,
							angle1, angle2);

			creationInterface->addEllipse(d);
		}
	}else{
		if(DEnko.m_dHenpeiRitsu == 1.0){
			//円弧
			if(DEnko.m_radEnkoKaku > 0.0){
				angle1 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku;
				angle2 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku + DEnko.m_radEnkoKaku;
			}else{
				angle1 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku + DEnko.m_radEnkoKaku;
				angle2 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku;
			}
			angle1 = angle1 - floor(angle1 / (M_PI * 2.0)) * M_PI * 2.0;
			angle2 = angle2 - floor(angle2 / (M_PI * 2.0)) * M_PI * 2.0;
			if( angle2 <= angle1 )
				angle1 = angle1 - M_PI * 2.0;
			DL_ArcData d(DEnko.m_start.x, DEnko.m_start.y, 0.0,
					DEnko.m_dHankei,
					Deg(angle1),
					Deg(angle2));

			creationInterface->addArc(d);
		}else{
			double angle1, angle2;
			if(DEnko.m_radEnkoKaku > 0.0){
				angle1 = DEnko.m_radKaishiKaku;
				angle2 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku;
			}else{
				angle1 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku;
				angle2 = DEnko.m_radKaishiKaku;
			}
			angle1 = angle1 - floor(angle1 / (M_PI * 2.0)) * M_PI * 2.0;
			angle2 = angle2 - floor(angle2 / (M_PI * 2.0)) * M_PI * 2.0;
			if( angle2 <= angle1 )
				angle1 = angle1 - M_PI * 2.0;
			//楕円
			DL_EllipseData d(DEnko.m_start.x, DEnko.m_start.y, 0.0,
							DEnko.m_dHankei * cos(DEnko.m_radKatamukiKaku), DEnko.m_dHankei * sin(DEnko.m_radKatamukiKaku), 0.0,
							DEnko.m_dHenpeiRitsu,
							angle1, angle2);

			creationInterface->addEllipse(d);
		}
	}
#ifdef FINISHED
	RS_CircleData data1(RS_Vector(0.0, 0.0), 0.0);
	RS_Circle* circle;
	RS_ArcData arc_data(RS_Vector(0.0, 0.0), 0.0, 0.0, 0.0, false);
	RS_Arc* arc;
	RS_Ellipse* elps;
	//正円
	if(DEnko.m_bZenEnFlg){
		if(DEnko.m_dHenpeiRitsu == 1.0){
			data1.center = RS_Vector(DEnko.m_start.x, DEnko.m_start.y);
			data1.radius = DEnko.m_dHankei;
			circle = new RS_Circle(graphic, data1);
			RS2::LineType ltype = lTable[DEnko.m_nPenStyle];
			RS_Color col = colTable[DEnko.m_nPenColor];
			RS2::LineWidth lw = lWidth[DEnko.m_nPenWidth > 26 ? 0 : DEnko.m_nPenWidth];//RS2::Width12
			circle->setPen(RS_Pen(col, lw, ltype));

			RS_String lName = HEX[DEnko.m_nGLayer > 0x0f ? 0:DEnko.m_nGLayer] + "-" +
				HEX[DEnko.m_nLayer > 0x0f ? 0: DEnko.m_nLayer];
			if( graphic->findLayer(lName) == (RS_Layer*)NULL ){
#ifdef DEBUG
std::cout << lName.ascii() << std::endl;
#endif
				RS_Layer* layer = new RS_Layer(lName);
				graphic->addLayer(layer);
			}
			circle->setLayer(lName);
			// add the line to the graphic
			graphic->addEntity(circle);
#ifdef DEBUG
std::cout << *circle;
#endif
		}else{
			//楕円
			double angle1, angle2;
			if(DEnko.m_radEnkoKaku > 0.0){
				angle1 = DEnko.m_radKaishiKaku;
				angle2 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku;
			}else{
				angle1 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku;
				angle2 = DEnko.m_radKaishiKaku;
			}
			angle1 = angle1 - floor(angle1 / (M_PI * 2.0)) * M_PI * 2.0;
			angle2 = angle2 - floor(angle2 / (M_PI * 2.0)) * M_PI * 2.0;
			if( angle2 <= angle1 )
				angle1 = angle1 - M_PI * 2.0;
			RS_EllipseData elps_data(RS_Vector(DEnko.m_start.x, DEnko.m_start.y),
									RS_Vector(DEnko.m_dHankei * cos(DEnko.m_radKatamukiKaku), DEnko.m_dHankei * sin(DEnko.m_radKatamukiKaku)),
									DEnko.m_dHenpeiRitsu,
									angle1, angle2, false);
			elps = new RS_Ellipse(graphic, elps_data);
			RS2::LineType ltype = lTable[DEnko.m_nPenStyle];
			RS_Color col = colTable[DEnko.m_nPenColor];
			RS2::LineWidth lw = lWidth[DEnko.m_nPenWidth > 26 ? 0 : DEnko.m_nPenWidth];//RS2::Width12
			elps->setPen(RS_Pen(col, lw, ltype));

			RS_String lName = HEX[DEnko.m_nGLayer > 0x0f ? 0:DEnko.m_nGLayer] + "-" +
				HEX[DEnko.m_nLayer > 0x0f ? 0: DEnko.m_nLayer];
			if( graphic->findLayer(lName) == (RS_Layer*)NULL ){
				RS_Layer* layer = new RS_Layer(lName);
				graphic->addLayer(layer);
			}
			elps->setLayer(lName);
			// add the line to the graphic
			graphic->addEntity(elps);
		}
	}else{
		//円弧
		arc_data.center = RS_Vector(DEnko.m_start.x, DEnko.m_start.y);
		arc_data.radius = DEnko.m_dHankei;
		if(DEnko.m_radEnkoKaku > 0.0){
			arc_data.angle1 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku;
			arc_data.angle2 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku + DEnko.m_radEnkoKaku;
		}else{
			arc_data.angle1 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku + DEnko.m_radEnkoKaku;
			arc_data.angle2 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku;
		}
		if( arc_data.angle2 <= arc_data.angle1 )
			arc_data.angle1 = arc_data.angle1 - M_PI * 2.0;
		arc_data.angle1 = Deg(arc_data.angle1);
		arc_data.angle2 = Deg(arc_data.angle2);
		arc_data.reversed = false;
		arc = new RS_Arc(graphic, arc_data);
		RS2::LineType ltype = lTable[DEnko.m_nPenStyle];
		RS_Color col = colTable[DEnko.m_nPenColor];
		RS2::LineWidth lw = lWidth[DEnko.m_nPenWidth > 26 ? 0 : DEnko.m_nPenWidth];//RS2::Width12
		arc->setPen(RS_Pen(col, lw, ltype));

		RS_String lName = HEX[DEnko.m_nGLayer > 0x0f ? 0:DEnko.m_nGLayer] + "-" +
			HEX[DEnko.m_nLayer > 0x0f ? 0: DEnko.m_nLayer];
		if( graphic->findLayer(lName) == (RS_Layer*)NULL ){
#ifdef DEBUG
std::cout << lName.ascii() << std::endl;
#endif
			RS_Layer* layer = new RS_Layer(lName);
			graphic->addLayer(layer);
		}
		arc->setLayer(lName);
		// add the line to the graphic
		graphic->addEntity(arc);
	}
#endif
}
Beispiel #5
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) {
        removeEntity(hatch);
		hatch = nullptr;
    }

    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) {
        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");
        delete pat;
        delete copy;
        updateError = HATCH_AREA_TOO_BIG;
        return;
    }

    f = copy->getMin().x/pSize.x;
    px1 = (int)floor(f);
    f = copy->getMin().y/pSize.y;
    py1 = (int)floor(f);
    f = copy->getMax().x/pSize.x;
    px2 = (int)ceil(f);
    f = copy->getMax().y/pSize.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(auto e: *pat){
                RS_Entity* te=e->clone();
                te->move(dvx*px + dvy*py);
                tmp.addEntity(te);
            }
        }
    }

    delete pat;
    pat = nullptr;
    delete copy;
    copy = nullptr;
    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 = nullptr;
	RS_Arc* arc = nullptr;
	RS_Circle* circle = nullptr;
	RS_Ellipse* ellipse = nullptr;
	for(auto e: tmp){

		line = nullptr;
		arc = nullptr;
		circle = nullptr;
		ellipse = nullptr;

        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;

		for(auto loop: entities){

            if (loop->isContainer()) {
				for(auto p: * static_cast<RS_EntityContainer*>(loop)){

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

					for (const RS_Vector& vp: sol){
						if (vp.valid) {
							is.append(std::shared_ptr<RS_Vector>(
										  new RS_Vector(vp)
										  ));
							RS_DEBUG->print("  pattern line intersection: %f/%f",
											vp.x, vp.y);
						}
					}
				}
			}
		}


        QList<std::shared_ptr<RS_Vector> > is2;//to be filled with sorted intersections
        is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(startPoint)));

        // sort the intersection points into is2 (only if there are intersections):
        if(is.size() == 1)
        {//only one intersection
            is2.append(is.first());
        }
        else if(is.size() > 1)
        {
            RS_Vector sp = startPoint;
            double sa = center.angleTo(sp);
			if(ellipse ) sa=ellipse->getEllipseAngle(sp);
            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()) {
                    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);
        }

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

        // 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) {

					tmp2.addEntity(new RS_Line{&tmp2, *v1, *v2});
                } else if (arc || circle) {
                    if(fabs(center.angleTo(*v2)-center.angleTo(*v1)) > RS_TOLERANCE_ANGLE)
                    {//don't create an arc with a too small angle
                        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(nullptr);
    hatch->setFlag(RS2::FlagTemp);

    //calculateBorders();

	for(auto e: tmp2){

        RS_Vector middlePoint;
        RS_Vector middlePoint2;
        if (e->rtti()==RS2::EntityLine) {
			RS_Line* line = static_cast<RS_Line*>(e);
            middlePoint = line->getMiddlePoint();
            middlePoint2 = line->getNearestDist(line->getLength()/2.1,
                                                line->getStartpoint());
        } else if (e->rtti()==RS2::EntityArc) {
			RS_Arc* arc = static_cast<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(RS2::FlagInvalid);
				te->setLayer(nullptr);
                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");
}
/**
 * Testing function.
 */
void LC_SimpleTests::slotTestInsertEllipse() {
	RS_DEBUG->print("%s\n: begin\n", __func__);
	auto appWin=QC_ApplicationWindow::getAppWindow();

	RS_Document* d = appWin->getDocument();
	if (d) {
		RS_Graphic* graphic = (RS_Graphic*)d;
		if (!graphic) {
			return;
		}

		RS_Ellipse* ellipse;
		RS_Line* line;

		for (double a=0.; a<2.*M_PI; a+=0.1) {
			RS_Vector v = RS_Vector::polar(50., a);
			double xp = 1000.*a;

			ellipse = new RS_Ellipse(graphic,
			{xp,0.}, v,
									 0.5,
									 0., 2.*M_PI,
									 false);

			ellipse->setPen(RS_Pen(RS_Color(255, 0, 255),
								   RS2::Width01,
								   RS2::SolidLine));

			graphic->addEntity(ellipse);
			//graphic->addEntity(new RS_Point(graphic, ellipse->getMax()));
			//graphic->addEntity(new RS_Point(graphic, ellipse->getMin()));

			line = new RS_Line{graphic, {xp, 0.}, RS_Vector{xp, 0.}+v};
			line->setPen(RS_Pen(RS_Color(128, 128, 128),
								RS2::Width01,
								RS2::SolidLine));
			graphic->addEntity(line);


			/*
					 for (double mx=-60.0; mx<60.0; mx+=1.0) {
						 //for (double mx=0.0; mx<1.0; mx+=2.5) {
						 RS_VectorSolutions sol = ellipse->mapX(xp + mx);
						 //graphic->addEntity(new RS_Point(graphic,
						 //                   sol.vector2 + RS_Vector(a*500.0, 0.0)));
						 //graphic->addEntity(new RS_Point(graphic,
						 //                   sol.vector3 + RS_Vector(a*500.0, 0.0)));
						 //graphic->addEntity(new RS_Point(graphic,
						 //                   sol.vector4 + RS_Vector(a*500.0, 0.0)));

						 line = new RS_Line(graphic,
											RS_LineData(RS_Vector(xp+mx,-50.0),
														RS_Vector(xp+mx,50.0)));
						 line->setPen(RS_Pen(RS_Color(60, 60, 60),
											 RS2::Width01,
											 RS2::SolidLine));
						 graphic->addEntity(line);

						 graphic->addEntity(new RS_Point(graphic,
														 sol.get(0)));
					 }
			*/
		}


		// different minor/minor relations
		/*
			  double x, y;
			  for (y=-250.0; y<=250.0; y+=50.0) {
				  for (x=-250.0; x<=250.0; x+=50.0) {
					  RS_Vector v(x, y);

					  ellipse = new RS_Ellipse(graphic,
											   v,
											   RS_Vector((x/5+50.0)/2.0, 0.0),
										 fabs(x/y),
											   0.0, 2*M_PI,
											   false);

				ellipse->setPen(RS_Pen(RS_Color(255, 255, 0),
									   RS2::Width01,
									   RS2::DashDotLine));

					  graphic->addEntity(ellipse);
					  graphic->addEntity(new RS_Point(graphic, ellipse->getMax()));
					  graphic->addEntity(new RS_Point(graphic, ellipse->getMin()));

				ellipse = new RS_Ellipse(graphic,
											   v + RS_Vector(750.0, 0.0),
											   RS_Vector((x/5+50.0)/2.0, 0.0),
											   fabs(x/y),
											   2*M_PI, 0.0,
											   true);

					  graphic->addEntity(ellipse);
					  graphic->addEntity(new RS_Point(graphic, ellipse->getMax()));
					  graphic->addEntity(new RS_Point(graphic, ellipse->getMin()));
				  }
			  }
		*/

		/*
			  // different rotation angles:
			  double rot;
			  for (rot=0.0; rot<=2*M_PI+0.1; rot+=(M_PI/8)) {
				  ellipse = new RS_Ellipse(graphic,
										   RS_Vector(rot*200, 500.0),
										   RS_Vector(50.0, 0.0).rotate(rot),
										   0.3,
										   0.0, 2*M_PI,
										   false);
				  graphic->addEntity(ellipse);
				  graphic->addEntity(new RS_Point(graphic, ellipse->getMax()));
				  graphic->addEntity(new RS_Point(graphic, ellipse->getMin()));
			  }


			  // different arc angles:
			  double a1, a2;
			  for (rot=0.0; rot<=2*M_PI+0.1; rot+=(M_PI/8)) {
				  for (a1=0.0; a1<=2*M_PI+0.1; a1+=(M_PI/8)) {
					  for (a2=a1+M_PI/8; a2<=2*M_PI+a1+0.1; a2+=(M_PI/8)) {
						  ellipse = new RS_Ellipse(graphic,
												   RS_Vector(-500.0-a1*200.0-5000.0*rot,
															 500.0-a2*200.0),
												   RS_Vector(50.0, 0.0).rotate(rot),
												   0.3,
												   a1, a2,
												   false);
						  graphic->addEntity(ellipse);
						  graphic->addEntity(new RS_Point(graphic, ellipse->getMax()));
						  graphic->addEntity(new RS_Point(graphic, ellipse->getMin()));
					  }
				  }
			  }
		*/

		RS_GraphicView* v = appWin->getGraphicView();
		if (v) {
			v->redraw();
		}
	}
	RS_DEBUG->print("%s\n: end\n", __func__);
}
void Plugin_Entity::updateData(QHash<int, QVariant> *data){
    if (entity == NULL) return;
    QHash<int, QVariant> hash = *data;
    QString str;
    RS_Vector vec;
    RS_Pen epen = entity->getPen();
//    double num;
    if (hash.contains(DPI::LAYER)) {
        str = (hash.take(DPI::LAYER)).toString();
        entity->setLayer(str);
    }
    if (hash.contains(DPI::LTYPE)) {
        str = (hash.take(DPI::LTYPE)).toString();
        epen.setLineType( Converter.str2lt(str) );
    }
    if (hash.contains(DPI::LWIDTH)) {
        str = (hash.take(DPI::LWIDTH)).toString();
        epen.setWidth( Converter.str2lw(str) );
    }
    if (hash.contains(DPI::COLOR)) {
        QColor color = hash.take(DPI::COLOR).value<QColor>();
        epen.setColor(color);
    }
    entity->setPen(epen);

    RS2::EntityType et = entity->rtti();
    switch (et) {
    //atomicEntity
    case RS2::EntityLine: {
        vec = static_cast<RS_Line*>(entity)->getStartpoint();
        if (hash.contains(DPI::STARTX)) {
            vec.x = (hash.take(DPI::STARTX)).toDouble();
        }
        if (hash.contains(DPI::STARTY)) {
            vec.y = (hash.take(DPI::STARTY)).toDouble();
        }
        static_cast<RS_Line*>(entity)->setStartpoint(vec);
        vec = static_cast<RS_Line*>(entity)->getEndpoint();
        if (hash.contains(DPI::ENDX)) {
            vec.x = (hash.take(DPI::ENDX)).toDouble();
        }
        if (hash.contains(DPI::ENDY)) {
            vec.y = (hash.take(DPI::ENDY)).toDouble();
        }
        static_cast<RS_Line*>(entity)->setEndpoint(vec);
        break;}
    case RS2::EntityPoint: {
        vec = static_cast<RS_Point*>(entity)->getPos();
        if (hash.contains(DPI::STARTX)) {
            vec.x = (hash.take(DPI::STARTX)).toDouble();
        }
        if (hash.contains(DPI::STARTY)) {
            vec.y = (hash.take(DPI::STARTY)).toDouble();
        }
        static_cast<RS_Point*>(entity)->setPos(vec);
        break; }
    case RS2::EntityArc: {
        RS_Arc *arc = static_cast<RS_Arc*>(entity);
        vec = arc->getCenter();
        if (hash.contains(DPI::STARTX)) {
            vec.x = (hash.take(DPI::STARTX)).toDouble();
        }
        if (hash.contains(DPI::STARTY)) {
            vec.y = (hash.take(DPI::STARTY)).toDouble();
        }
        arc->setCenter(vec);
        if (hash.contains(DPI::RADIUS)) {
            arc->setRadius( (hash.take(DPI::RADIUS)).toDouble() );
        }
        if (hash.contains(DPI::STARTANGLE)) {
             arc->setAngle1( (hash.take(DPI::STARTANGLE)).toDouble() );
           vec.y = (hash.take(DPI::STARTANGLE)).toDouble();
        }
        if (hash.contains(DPI::ENDANGLE)) {
            arc->setAngle2( (hash.take(DPI::ENDANGLE)).toDouble() );
        }
        break;}
    case RS2::EntityCircle: {
        RS_Circle *cir = static_cast<RS_Circle*>(entity);
        vec = cir->getCenter();
        if (hash.contains(DPI::STARTX)) {
            vec.x = (hash.take(DPI::STARTX)).toDouble();
        }
        if (hash.contains(DPI::STARTY)) {
            vec.y = (hash.take(DPI::STARTY)).toDouble();
        }
        cir->setCenter(vec);
        if (hash.contains(DPI::RADIUS)) {
            cir->setRadius( (hash.take(DPI::RADIUS)).toDouble() );
        }
        break;}
    case RS2::EntityEllipse: {
        RS_Ellipse *ellipse = static_cast<RS_Ellipse*>(entity);
        vec = ellipse->getCenter();
        if (hash.contains(DPI::STARTX)) {
            vec.x = (hash.take(DPI::STARTX)).toDouble();
        }
        if (hash.contains(DPI::STARTY)) {
            vec.y = (hash.take(DPI::STARTY)).toDouble();
        }
        ellipse->setCenter(vec);

        vec = ellipse->getMajorP();
        if (hash.contains(DPI::ENDX)) {
            vec.x = (hash.take(DPI::ENDX)).toDouble();
        }
        if (hash.contains(DPI::ENDY)) {
            vec.y = (hash.take(DPI::ENDY)).toDouble();
        }
        ellipse->setMajorP(vec);

        if (hash.contains(DPI::STARTANGLE)) {
            ellipse->setAngle1((hash.take(DPI::STARTANGLE)).toDouble());
        }
        if (hash.contains(DPI::ENDANGLE)) {
            ellipse->setAngle2((hash.take(DPI::ENDANGLE)).toDouble());
        }
        if (hash.contains(DPI::HEIGHT)) {
            ellipse->setRatio((hash.take(DPI::HEIGHT)).toDouble());
        }
        if (hash.contains(DPI::REVERSED)) {
            ellipse->setReversed( (hash.take(DPI::REVERSED)).toBool());
        }
        break;}
    case RS2::EntitySolid: //TODO
        //Only used in dimensions ?
        break;
    case RS2::EntityConstructionLine:
        //Unused ?
        break;
    case RS2::EntityImage: {
        break;}
    case RS2::EntityOverlayBox:
        //Unused ?
        break;
//EntityContainer
    case RS2::EntityInsert: {
        break;}
    case RS2::EntityText: {
        RS_Text *txt = static_cast<RS_Text*>(entity);
        bool move = false;
        vec = txt->getInsertionPoint();
        if (hash.contains(DPI::STARTX)) {
            vec.x = (hash.take(DPI::STARTX)).toDouble() - vec.x;
            move = true;
        } else vec.x = 0;
        if (hash.contains(DPI::STARTY)) {
            vec.y = (hash.take(DPI::STARTY)).toDouble() - vec.y;
            move = true;
        } else vec.y = 0;
        if (move)
            txt->move(vec);
        if (hash.contains(DPI::TEXTCONTENT)) {
            txt->setText( (hash.take(DPI::TEXTCONTENT)).toString() );
        }
        if (hash.contains(DPI::STARTANGLE)) {
            txt->setAngle( (hash.take(DPI::STARTANGLE)).toDouble() );
        }
        if (hash.contains(DPI::HEIGHT)) {
            txt->setHeight( (hash.take(DPI::HEIGHT)).toDouble() );
        }
        break;}
    case RS2::EntityHatch:
        break;
    case RS2::EntitySpline:
        break;
    case RS2::EntityPolyline: {
        RS_Polyline *pl = static_cast<RS_Polyline*>(entity);
        if (hash.take(DPI::CLOSEPOLY).toBool()) {
            pl->setClosed(true);
        }else{
            pl->setClosed(false);
        }
        break;}
    case RS2::EntityVertex:
        break;
    case RS2::EntityDimAligned:
        break;
    case RS2::EntityDimLinear:
        break;
    case RS2::EntityDimRadial:
        break;
    case RS2::EntityDimDiametric:
        break;
    case RS2::EntityDimAngular:
        break;
    case RS2::EntityDimLeader:
        break;
    case RS2::EntityUnknown:
    default:
        break;
    }
    entity->update();
}
void Plugin_Entity::getData(QHash<int, QVariant> *data){
    if (entity == NULL) return;
    RS2::EntityType et = entity->rtti();
    data->insert(DPI::EID, (qulonglong)entity->getId());
    data->insert(DPI::LAYER, entity->getLayer()->getName() );
    data->insert(DPI::LTYPE, Converter.lt2str(entity->getPen().getLineType()) );
    data->insert(DPI::LWIDTH, Converter.lw2str(entity->getPen().getWidth()) );
    data->insert(DPI::COLOR, entity->getPen().getColor() );
    switch (et) {
    //atomicEntity
    case RS2::EntityLine: {
        data->insert(DPI::ETYPE, DPI::LINE);
        RS_LineData d = static_cast<RS_Line*>(entity)->getData();
        data->insert(DPI::STARTX, d.startpoint.x );
        data->insert(DPI::STARTY, d.startpoint.y );
        data->insert(DPI::ENDX, d.endpoint.x );
        data->insert(DPI::ENDY, d.endpoint.y );
        break;}
    case RS2::EntityPoint: {
        data->insert(DPI::ETYPE, DPI::POINT);
        RS_PointData d = static_cast<RS_Point*>(entity)->getData();
        data->insert(DPI::STARTX, d.pos.x );
        data->insert(DPI::STARTY, d.pos.y );
        break; }
    case RS2::EntityArc: {
        data->insert(DPI::ETYPE, DPI::ARC);
        RS_ArcData d = static_cast<RS_Arc*>(entity)->getData();
        data->insert(DPI::STARTX, d.center.x );
        data->insert(DPI::STARTY, d.center.y );
        data->insert(DPI::RADIUS, d.radius );
        data->insert(DPI::STARTANGLE, d.angle1 );
        data->insert(DPI::ENDANGLE, d.angle2 );
        data->insert(DPI::REVERSED, d.reversed );
        break;}
    case RS2::EntityCircle: {
        data->insert(DPI::ETYPE, DPI::CIRCLE);
        RS_CircleData d = static_cast<RS_Circle*>(entity)->getData();
        data->insert(DPI::STARTX, d.center.x );
        data->insert(DPI::STARTY, d.center.y );
        data->insert(DPI::RADIUS, d.radius );
        break;}
    case RS2::EntityEllipse: {
        data->insert(DPI::ETYPE, DPI::ELLIPSE);
//        RS_EllipseData d = static_cast<RS_Ellipse*>(entity)->getData();
        RS_Ellipse *dd = static_cast<RS_Ellipse*>(entity);
        data->insert(DPI::STARTX, dd->getCenter().x );//10
        data->insert(DPI::STARTY, dd->getCenter().y );//20
        data->insert(DPI::ENDX, dd->getMajorP().x );//11 endpoint major axis x
        data->insert(DPI::ENDY, dd->getMajorP().y );//21 endpoint major axis y
        data->insert(DPI::HEIGHT, dd->getRatio() );//40 major/minor axis ratio
        data->insert(DPI::STARTANGLE, dd->getAngle1() );
        data->insert(DPI::ENDANGLE, dd->getAngle2() );
        data->insert(DPI::REVERSED, dd->isReversed() );
        break;}
    case RS2::EntitySolid: //TODO
        //Only used in dimensions ?
        data->insert(DPI::ETYPE, DPI::SOLID);
        break;
    case RS2::EntityConstructionLine:
        //Unused ?
        data->insert(DPI::ETYPE, DPI::CONSTRUCTIONLINE);
        break;
    case RS2::EntityImage: {
        data->insert(DPI::ETYPE, DPI::IMAGE);
        RS_ImageData d = static_cast<RS_Image*>(entity)->getData();
        data->insert(DPI::STARTX, d.insertionPoint.x );
        data->insert(DPI::STARTY, d.insertionPoint.y );
        break;}
    case RS2::EntityOverlayBox:
        //Unused ?
        data->insert(DPI::ETYPE, DPI::OVERLAYBOX);
        break;
//EntityContainer
    case RS2::EntityInsert: {
        data->insert(DPI::ETYPE, DPI::INSERT);
        RS_InsertData d = static_cast<RS_Insert*>(entity)->getData();
        data->insert(DPI::STARTX, d.insertionPoint.x );
        data->insert(DPI::STARTY, d.insertionPoint.y );
        data->insert(DPI::BLKNAME, d.name );
        data->insert(DPI::STARTANGLE, d.angle );
        data->insert(DPI::XSCALE, d.scaleFactor.x );
        data->insert(DPI::YSCALE, d.scaleFactor.y );
        break;}
    case RS2::EntityText: {
        data->insert(DPI::ETYPE, DPI::TEXT);
        RS_TextData d = static_cast<RS_Text*>(entity)->getData();
        data->insert(DPI::STARTX, d.insertionPoint.x );
        data->insert(DPI::STARTY, d.insertionPoint.y );
        data->insert(DPI::STARTANGLE, d.angle );
        data->insert(DPI::HEIGHT, d.height );
        data->insert(DPI::TEXTCONTENT, d.text );
        break;}
    case RS2::EntityHatch:
        data->insert(DPI::ETYPE, DPI::HATCH);
        break;
    case RS2::EntitySpline:
        data->insert(DPI::ETYPE, DPI::SPLINE);
        break;
    case RS2::EntityPolyline:
        data->insert(DPI::ETYPE, DPI::POLYLINE);
        data->insert(DPI::CLOSEPOLY, static_cast<RS_Polyline*>(entity)->isClosed() );
        break;
    case RS2::EntityVertex:
        data->insert(DPI::ETYPE, DPI::UNKNOWN);
        break;
    case RS2::EntityDimAligned:
        data->insert(DPI::ETYPE, DPI::DIMALIGNED);
        break;
    case RS2::EntityDimLinear:
        data->insert(DPI::ETYPE, DPI::DIMLINEAR);
        break;
    case RS2::EntityDimRadial:
        data->insert(DPI::ETYPE, DPI::DIMRADIAL);
        break;
    case RS2::EntityDimDiametric:
        data->insert(DPI::ETYPE, DPI::DIMDIAMETRIC);
        break;
    case RS2::EntityDimAngular:
        data->insert(DPI::ETYPE, DPI::DIMANGULAR);
        break;
    case RS2::EntityDimLeader:
        data->insert(DPI::ETYPE, DPI::DIMLEADER);
        break;
    case RS2::EntityUnknown:
    default:
        data->insert(DPI::ETYPE, DPI::UNKNOWN);
        break;
    }
}
Beispiel #9
0
/** construct a ellipse or hyperbola as the path of center of common tangent circles
  of this two given entities*/
LC_Quadratic::LC_Quadratic(const RS_AtomicEntity* circle0,
                           const RS_AtomicEntity* circle1,
                           bool mirror):
    m_mQuad(2,2)
    ,m_vLinear(2)
    ,m_bValid(false)
{
//    DEBUG_HEADER

	if(!( circle0->isArcCircleLine() && circle1->isArcCircleLine())) {
		return;
	}

	if(circle1->rtti() != RS2::EntityLine)
        std::swap(circle0, circle1);
    if(circle0->rtti() == RS2::EntityLine) {
        //two lines
        RS_Line* line0=(RS_Line*) circle0;
        RS_Line* line1=(RS_Line*) circle1;

		auto centers=RS_Information::getIntersection(line0,line1);
//        DEBUG_HEADER
        if(centers.size()!=1) return;
        double angle=0.5*(line0->getAngle1()+line1->getAngle1());
        m_bValid=true;
        m_bIsQuadratic=true;
        m_mQuad(0,0)=0.;
        m_mQuad(0,1)=0.5;
        m_mQuad(1,0)=0.5;
        m_mQuad(1,1)=0.;
        m_vLinear(0)=0.;
        m_vLinear(1)=0.;
        m_dConst=0.;
        rotate(angle);
        move(centers.get(0));
//        DEBUG_HEADER
//        std::cout<<*this<<std::endl;
        return;
    }
    if(circle1->rtti() == RS2::EntityLine) {
//        DEBUG_HEADER
        //one line, one circle
        const RS_Line* line1=static_cast<const RS_Line*>(circle1);
        RS_Vector normal=line1->getNormalVector()*circle0->getRadius();
        RS_Vector disp=line1->getNearestPointOnEntity(circle0->getCenter(),
                                                           false)-circle0->getCenter();
	if(normal.dotP(disp)>0.) normal *= -1.;
    if(mirror) normal *= -1.;
							   
		RS_Line directrix{line1->getStartpoint()+normal,
										   line1->getEndpoint()+normal};
        LC_Quadratic lc0(&directrix,circle0->getCenter());
        *this = lc0;
        return;

        m_mQuad=lc0.getQuad();
        m_vLinear=lc0.getLinear();
        m_bIsQuadratic=true;
        m_bValid=true;
        m_dConst=lc0.m_dConst;

        return;
    }
    //two circles

	double const f=(circle0->getCenter()-circle1->getCenter()).magnitude()*0.5;
	double const a=fabs(circle0->getRadius()+circle1->getRadius())*0.5;
	double const c=fabs(circle0->getRadius()-circle1->getRadius())*0.5;
//    DEBUG_HEADER
//    qDebug()<<"circle center to center distance="<<2.*f<<"\ttotal radius="<<2.*a;
    if(a<RS_TOLERANCE) return;
	RS_Vector center=(circle0->getCenter()+circle1->getCenter())*0.5;
    double angle=center.angleTo(circle0->getCenter());
    if( f<a){
        //ellipse
		double const ratio=sqrt(a*a - f*f)/a;
		RS_Vector const& majorP=RS_Vector{angle}*a;
		RS_Ellipse const ellipse{center,majorP,ratio,0.,0.,false};
		auto const& lc0=ellipse.getQuadratic();

        m_mQuad=lc0.getQuad();
        m_vLinear=lc0.getLinear();
        m_bIsQuadratic=lc0.isQuadratic();
        m_bValid=lc0.isValid();
        m_dConst=lc0.m_dConst;
//        DEBUG_HEADER
//        std::cout<<"ellipse: "<<*this;
        return;
    }

//       DEBUG_HEADER
	if(c<RS_TOLERANCE){
		//two circles are the same radius
		//degenerate hypberbola: straight lines
		//equation xy = 0
		m_bValid=true;
		m_bIsQuadratic=true;
		m_mQuad(0,0)=0.;
		m_mQuad(0,1)=0.5;
		m_mQuad(1,0)=0.5;
		m_mQuad(1,1)=0.;
		m_vLinear(0)=0.;
		m_vLinear(1)=0.;
		m_dConst=0.;
		rotate(angle);
		move(center);
		return;
	}
//hyperbola
	// equation: x^2/c^2 - y^2/(f^2 -c ^2) = 1
	// f: from hyperbola center to one circle center
	// c: half of difference of two circles

    double b2= f*f - c*c;
    m_bValid=true;
    m_bIsQuadratic=true;
	m_mQuad(0,0)=1./(c*c);
    m_mQuad(0,1)=0.;
    m_mQuad(1,0)=0.;
    m_mQuad(1,1)=-1./b2;
    m_vLinear(0)=0.;
    m_vLinear(1)=0.;
    m_dConst=-1.;
    rotate(angle);
    move(center);
    return;
}
Beispiel #10
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");
}
Beispiel #11
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;
    }