📄 rs_information.cpp
字号:
/****************************************************************************** $Id: rs_information.cpp 2378 2005-05-16 17:05:15Z andrew $**** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.**** This file is part of the qcadlib Library project.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid qcadlib Professional Edition licenses may use ** this file in accordance with the qcadlib Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.ribbonsoft.com for further details.**** Contact info@ribbonsoft.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "rs_information.h"#include "rs_constructionline.h"/** * Default constructor. * * @param container The container to which we will add * entities. Usually that's an RS_Graphic entity but * it can also be a polyline, text, ... */RS_Information::RS_Information(RS_EntityContainer& container) { this->container = &container;}/** * @return true: if the entity is a dimensioning enity. * false: otherwise */bool RS_Information::isDimension(RS2::EntityType type) { if (type==RS2::EntityDimAligned || type==RS2::EntityDimLinear || type==RS2::EntityDimRadial || type==RS2::EntityDimDiametric || type==RS2::EntityDimAngular) { return true; } else { return false; }}/** * @retval true the entity can be trimmed. * i.e. it is in a graphic or in a polyline. */bool RS_Information::isTrimmable(RS_Entity* e) { if (e!=NULL) { if (e->getParent()!=NULL) { if (e->getParent()->rtti()==RS2::EntityPolyline) { return true; } else if (e->getParent()->rtti()==RS2::EntityContainer || e->getParent()->rtti()==RS2::EntityGraphic || e->getParent()->rtti()==RS2::EntityBlock) { // normal entity: return true; } } } return false;}/** * @retval true the two entities can be trimmed to each other; * i.e. they are in a graphic or in the same polyline. */bool RS_Information::isTrimmable(RS_Entity* e1, RS_Entity* e2) { if (e1!=NULL && e2!=NULL) { if (e1->getParent()!=NULL && e2->getParent()!=NULL) { if (e1->getParent()->rtti()==RS2::EntityPolyline && e2->getParent()->rtti()==RS2::EntityPolyline && e1->getParent()==e2->getParent()) { // in the same polyline RS_EntityContainer* pl = e1->getParent(); int idx1 = pl->findEntity(e1); int idx2 = pl->findEntity(e2); RS_DEBUG->print("RS_Information::isTrimmable: " "idx1: %d, idx2: %d", idx1, idx2); if (abs(idx1-idx2)==1 || abs(idx1-idx2)==pl->count()-1) { // directly following entities return true; } else { // not directly following entities return false; } } else if ((e1->getParent()->rtti()==RS2::EntityContainer || e1->getParent()->rtti()==RS2::EntityGraphic || e1->getParent()->rtti()==RS2::EntityBlock) && (e2->getParent()->rtti()==RS2::EntityContainer || e2->getParent()->rtti()==RS2::EntityGraphic || e2->getParent()->rtti()==RS2::EntityBlock)) { // normal entities: return true; } } else { // independent entities with the same parent: return (e1->getParent()==e2->getParent()); } } return false;}/** * Gets the nearest end point to the given coordinate. * * @param coord Coordinate (typically a mouse coordinate) * * @return the coordinate found or an invalid vector * if there are no elements at all in this graphics * container. */RS_Vector RS_Information::getNearestEndpoint(const RS_Vector& coord, double* dist) const { return container->getNearestEndpoint(coord, dist);}/** * Gets the nearest point to the given coordinate which is on an entity. * * @param coord Coordinate (typically a mouse coordinate) * @param dist Pointer to a double which will contain the * measured distance after return or NULL * @param entity Pointer to a pointer which will point to the * entity on which the point is or NULL * * @return the coordinate found or an invalid vector * if there are no elements at all in this graphics * container. */RS_Vector RS_Information::getNearestPointOnEntity(const RS_Vector& coord, bool onEntity, double* dist, RS_Entity** entity) const { return container->getNearestPointOnEntity(coord, onEntity, dist, entity);}/** * Gets the nearest entity to the given coordinate. * * @param coord Coordinate (typically a mouse coordinate) * @param dist Pointer to a double which will contain the * masured distance after return * @param level Level of resolving entities. * * @return the entity found or NULL if there are no elements * at all in this graphics container. */RS_Entity* RS_Information::getNearestEntity(const RS_Vector& coord, double* dist, RS2::ResolveLevel level) const { return container->getNearestEntity(coord, dist, level);}/** * Calculates the intersection point(s) between two entities. * * @param onEntities true: only return intersection points which are * on both entities. * false: return all intersection points. * * @todo support more entities * * @return All intersections of the two entities. The tangent flag in * RS_VectorSolutions is set if one intersection is a tangent point. */RS_VectorSolutions RS_Information::getIntersection(RS_Entity* e1, RS_Entity* e2, bool onEntities) { RS_VectorSolutions ret; double tol = 1.0e-4; if (e1==NULL || e2==NULL) { return ret; } // unsupported entities / entity combinations: if ((e1->rtti()==RS2::EntityEllipse && e2->rtti()==RS2::EntityEllipse) || e1->rtti()==RS2::EntityText || e2->rtti()==RS2::EntityText || isDimension(e1->rtti()) || isDimension(e2->rtti())) { return ret; } // (only) one entity is an ellipse: if (e1->rtti()==RS2::EntityEllipse || e2->rtti()==RS2::EntityEllipse) { if (e2->rtti()==RS2::EntityEllipse) { RS_Entity* tmp = e1; e1 = e2; e2 = tmp; } if (e2->rtti()==RS2::EntityLine) { RS_Ellipse* ellipse = (RS_Ellipse*)e1; ret = getIntersectionLineEllipse((RS_Line*)e2, ellipse); tol = 1.0e-1; } // ellipse / arc, ellipse / ellipse: not supported: else { return ret; } } else { RS_Entity* te1 = e1; RS_Entity* te2 = e2; // entity copies - so we only have to deal with lines and arcs RS_Line l1(NULL, RS_LineData(RS_Vector(0.0, 0.0), RS_Vector(0.0,0.0))); RS_Line l2(NULL, RS_LineData(RS_Vector(0.0, 0.0), RS_Vector(0.0,0.0))); RS_Arc a1(NULL, RS_ArcData(RS_Vector(0.0,0.0), 1.0, 0.0, 2*M_PI, false)); RS_Arc a2(NULL, RS_ArcData(RS_Vector(0.0,0.0), 1.0, 0.0, 2*M_PI, false)); // convert construction lines to lines: if (e1->rtti()==RS2::EntityConstructionLine) { RS_ConstructionLine* cl = (RS_ConstructionLine*)e1; l1.setStartpoint(cl->getPoint1()); l1.setEndpoint(cl->getPoint2()); te1 = &l1; } if (e2->rtti()==RS2::EntityConstructionLine) { RS_ConstructionLine* cl = (RS_ConstructionLine*)e2; l2.setStartpoint(cl->getPoint1()); l2.setEndpoint(cl->getPoint2()); te2 = &l2; } // convert circles to arcs: if (e1->rtti()==RS2::EntityCircle) { RS_Circle* c = (RS_Circle*)e1; RS_ArcData data(c->getCenter(), c->getRadius(), 0.0, 2*M_PI, false); a1.setData(data); te1 = &a1; } if (e2->rtti()==RS2::EntityCircle) { RS_Circle* c = (RS_Circle*)e2; RS_ArcData data(c->getCenter(), c->getRadius(), 0.0, 2*M_PI, false); a2.setData(data); te2 = &a2; } // line / line: // //else if (te1->rtti()==RS2::EntityLine && te2->rtti()==RS2::EntityLine) { RS_Line* line1 = (RS_Line*)te1; RS_Line* line2 = (RS_Line*)te2; ret = getIntersectionLineLine(line1, line2); } // line / arc: // else if (te1->rtti()==RS2::EntityLine && te2->rtti()==RS2::EntityArc) { RS_Line* line = (RS_Line*)te1; RS_Arc* arc = (RS_Arc*)te2; ret = getIntersectionLineArc(line, arc); } // arc / line: // else if (te1->rtti()==RS2::EntityArc && te2->rtti()==RS2::EntityLine) { RS_Arc* arc = (RS_Arc*)te1; RS_Line* line = (RS_Line*)te2; ret = getIntersectionLineArc(line, arc); } // arc / arc: // else if (te1->rtti()==RS2::EntityArc && te2->rtti()==RS2::EntityArc) { RS_Arc* arc1 = (RS_Arc*)te1; RS_Arc* arc2 = (RS_Arc*)te2; ret = getIntersectionArcArc(arc1, arc2); } else { RS_DEBUG->print("RS_Information::getIntersection:: Unsupported entity type."); } } // Check all intersection points for being on entities: // if (onEntities==true) { if (!e1->isPointOnEntity(ret.get(0), tol) || !e2->isPointOnEntity(ret.get(0), tol)) { ret.set(0, RS_Vector(false)); } if (!e1->isPointOnEntity(ret.get(1), tol) || !e2->isPointOnEntity(ret.get(1), tol)) { ret.set(1, RS_Vector(false)); } if (!e1->isPointOnEntity(ret.get(2), tol) || !e2->isPointOnEntity(ret.get(2), tol)) { ret.set(2, RS_Vector(false)); } if (!e1->isPointOnEntity(ret.get(3), tol) || !e2->isPointOnEntity(ret.get(3), tol)) { ret.set(3, RS_Vector(false)); } } int k=0; for (int i=0; i<4; ++i) { if (ret.get(i).valid) { ret.set(k, ret.get(i)); k++; } } for (int i=k; i<4; ++i) { ret.set(i, RS_Vector(false)); } return ret;}/** * @return Intersection between two lines. */RS_VectorSolutions RS_Information::getIntersectionLineLine(RS_Line* e1, RS_Line* e2) { RS_VectorSolutions ret; if (e1==NULL || e2==NULL) { return ret; } RS_Vector p1 = e1->getStartpoint(); RS_Vector p2 = e1->getEndpoint(); RS_Vector p3 = e2->getStartpoint(); RS_Vector p4 = e2->getEndpoint(); double num = ((p4.x-p3.x)*(p1.y-p3.y) - (p4.y-p3.y)*(p1.x-p3.x)); double div = ((p4.y-p3.y)*(p2.x-p1.x) - (p4.x-p3.x)*(p2.y-p1.y)); if (fabs(div)>RS_TOLERANCE) { double u = num / div; double xs = p1.x + u * (p2.x-p1.x); double ys = p1.y + u * (p2.y-p1.y); ret = RS_VectorSolutions(RS_Vector(xs, ys)); } // lines are parallel else { ret = RS_VectorSolutions(); } return ret;}/** * @return One or two intersection points between given entities.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -