| /**************************************************************************** | |
| ** | |
| ** This file is part of the LibreCAD project, a 2D CAD program | |
| ** | |
| ** Copyright (C) 2015 A. Stebich (librecad@mail.lordofbikes.de) | |
| ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl) | |
| ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved. | |
| ** | |
| ** | |
| ** 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 gpl-2.0.txt included in the | |
| ** packaging of this file. | |
| ** | |
| ** This program is distributed in the hope that it will be useful, | |
| ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| ** GNU General Public License for more details. | |
| ** | |
| ** You should have received a copy of the GNU General Public License | |
| ** along with this program; if not, write to the Free Software | |
| ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| ** | |
| ** This copyright notice MUST APPEAR in all copies of the script! | |
| ** | |
| **********************************************************************/ | |
| class RS_Pen; | |
| class RS_Line; | |
| class RS_Layer; | |
| class RS_Document; | |
| class RS_Insert; | |
| class RS_Block; | |
| class RS_Graphic; | |
| class RS_EntityContainer; | |
| class LC_Quadratic; | |
| /** | |
| * Base class for an entity (line, arc, circle, ...) | |
| * | |
| * @author Andrew Mustun | |
| */ | |
| class RS_Entity:public RS_Undoable, public LC_Drawable { | |
| public: | |
| RS_Entity(RS_EntityContainer *parent = nullptr); | |
| // RS_Entity(RS_EntityContainer *parent, bool setPenToActive = false); | |
| RS_Entity(const RS_Entity& entity); | |
| RS_Entity& operator = (const RS_Entity& entity); | |
| RS_Entity(RS_Entity&& entity); | |
| RS_Entity& operator = (RS_Entity&& entity); | |
| ~RS_Entity() override; | |
| virtual RS_Entity *clone() const = 0; | |
| virtual RS_Entity *cloneProxy() const; | |
| virtual void reparent(RS_EntityContainer *parent){ | |
| this->parent = parent; | |
| } | |
| void resetBorders(); | |
| void moveBorders(const RS_Vector &offset); | |
| void scaleBorders(const RS_Vector ¢er, const RS_Vector &factor); | |
| /** | |
| * Identify all entities as undoable entities. | |
| * @return RS2::UndoableEntity | |
| */ | |
| RS2::UndoableType undoRtti() const override{ | |
| return RS2::UndoableEntity; | |
| } | |
| /** | |
| * @return Unique Id of this entity. | |
| */ | |
| unsigned long long getId() const; | |
| /** | |
| * This method must be overwritten in subclasses and return the | |
| * number of <b>atomic</b> entities in this entity. | |
| */ | |
| virtual unsigned int count() const = 0; | |
| /** | |
| * This method must be overwritten in subclasses and return the | |
| * number of <b>atomic</b> entities in this entity including sub containers. | |
| */ | |
| virtual unsigned int countDeep() const = 0; | |
| /** | |
| * Implementations must return the total length of the entity | |
| * or a negative number if the entity has no length (e.g. a text or hatch). | |
| */ | |
| virtual double getLength() const{ | |
| return -1.0; | |
| } | |
| /** | |
| * @return Parent of this entity or nullptr if this is a root entity. | |
| */ | |
| RS_EntityContainer *getParent() const{ | |
| return parent; | |
| } | |
| /** | |
| * Reparents this entity. | |
| */ | |
| void setParent(RS_EntityContainer *p){ | |
| parent = p; | |
| } | |
| /** @return The center point (x) of this arc */ | |
| //get center for entities arc, circle and ellipse | |
| virtual RS_Vector getCenter() const; | |
| virtual double getRadius() const; | |
| virtual void setRadius(double r); | |
| virtual RS_Graphic* getGraphic() const; | |
| RS_Block *getBlock() const; | |
| RS_Insert *getInsert() const; | |
| RS_Entity *getBlockOrInsert() const; | |
| RS_Document *getDocument() const; | |
| void setLayer(const QString &name); | |
| void setLayer(RS_Layer *l); | |
| void setLayerToActive(); | |
| RS_Layer *getLayer(bool resolve = true) const; | |
| RS_Layer *getLayerResolved() const; | |
| /** | |
| * Sets the explicit pen for this entity or a pen with special | |
| * attributes such as BY_LAYER, .. | |
| */ | |
| void setPen(const RS_Pen &pen); | |
| void setPenToActive(); | |
| RS_Pen getPen(bool resolve = true) const; | |
| RS_Pen getPenResolved() const; | |
| /** | |
| * Must be overwritten to return true if an entity type | |
| * is a container for other entities (e.g. polyline, group, ...). | |
| */ | |
| virtual bool isContainer() const = 0; | |
| /** | |
| * Must be overwritten to return true if an entity type | |
| * is an atomic entity. | |
| */ | |
| virtual bool isAtomic() const = 0; | |
| /** | |
| * Must be overwritten to return true if an entity type | |
| * is a potential edge entity of a contour. By default | |
| * this returns false. | |
| */ | |
| virtual bool isEdge() const{ | |
| return false; | |
| } | |
| /** | |
| * @return true for all document entities (e.g. Graphics or Blocks). | |
| * false otherwise. | |
| */ | |
| virtual bool isDocument() const{ | |
| return false; | |
| } | |
| virtual bool setSelected(bool select); | |
| virtual bool toggleSelected(); | |
| virtual bool isSelected() const; | |
| bool isParentSelected() const; | |
| virtual bool isProcessed() const; | |
| virtual void setProcessed(bool on); | |
| bool isInWindow(RS_Vector v1, RS_Vector v2) const; | |
| virtual bool hasEndpointsWithinWindow(const RS_Vector & /*v1*/, const RS_Vector & /*v2*/) const { | |
| return false; | |
| } | |
| virtual bool isVisible() const; | |
| virtual void setVisible(bool v); | |
| virtual void setHighlighted(bool on); | |
| virtual bool isHighlighted() const; | |
| bool isTransparent() const; | |
| void setTransparent(bool on); | |
| bool isLocked() const; | |
| void undoStateChanged(bool undone) override; | |
| virtual bool isUndone() const; | |
| /** | |
| * Can be implemented by child classes to update the entities | |
| * temporary subentities. update() is called if the entity's | |
| * parameters or undo state changed. | |
| */ | |
| virtual void update(){} | |
| virtual void setUpdateEnabled(bool on){ | |
| updateEnabled = on; | |
| } | |
| /** | |
| * This method doesn't do any calculations. | |
| * @return minimum coordinate of the entity. | |
| * @see calculateBorders() | |
| */ | |
| RS_Vector getMin() const{ | |
| return minV; | |
| } | |
| /** | |
| * This method doesn't do any calculations. | |
| * @return minimum coordinate of the entity. | |
| * @see calculateBorders() | |
| */ | |
| RS_Vector getMax() const{ | |
| return maxV; | |
| } | |
| /** | |
| * This method returns the difference of max and min returned | |
| * by the above functions. | |
| * @return size of the entity. | |
| * @see calculateBorders() | |
| * @see getMin() | |
| * @see getMax() | |
| */ | |
| RS_Vector getSize() const; | |
| void addGraphicVariable(const QString &key, double val, int code); | |
| void addGraphicVariable(const QString &key, int val, int code); | |
| void addGraphicVariable(const QString &key, const QString &val, int code); | |
| double getGraphicVariableDouble(const QString &key, double def); | |
| int getGraphicVariableInt(const QString &key, int def) const; | |
| QString getGraphicVariableString( | |
| const QString &key, | |
| const QString &def) const; | |
| virtual RS_Vector getStartpoint() const; | |
| virtual RS_Vector getEndpoint() const; | |
| //find the local direction at end points, derived entities | |
| // must implement this if direction is supported by the entity type | |
| virtual double getDirection1() const{ | |
| return 0.; | |
| } | |
| virtual double getDirection2() const{ | |
| return 0.; | |
| } | |
| //find the tangential points seeing from given point | |
| virtual RS_VectorSolutions getTangentPoint(const RS_Vector & /*point*/) const; | |
| virtual RS_Vector getTangentDirection(const RS_Vector & /*point*/) const; | |
| RS2::Unit getGraphicUnit() const; | |
| /** | |
| * Must be overwritten to get all reference points of the entity. | |
| */ | |
| virtual RS_VectorSolutions getRefPoints() const; | |
| /** | |
| * Must be overwritten to get the closest endpoint to the | |
| * given coordinate for this entity. | |
| * | |
| * @param coord Coordinate (typically a mouse coordinate) | |
| * @param dist Pointer to a value which will contain the measured | |
| * distance between 'coord' and the closest endpoint. The passed | |
| * pointer can also be nullptr in which case the distance will be | |
| * lost. | |
| * | |
| * @return The closest endpoint. | |
| */ | |
| virtual RS_Vector getNearestEndpoint( | |
| const RS_Vector &coord, | |
| double *dist = nullptr) const = 0; | |
| /** | |
| * Must be overwritten to get the closest coordinate to the | |
| * given coordinate which is on this entity. | |
| * | |
| * @param coord Coordinate (typically a mouse coordinate) | |
| * @param dist Pointer to a value which will contain the measured | |
| * distance between \p coord and the point. The passed pointer can | |
| * also be \p nullptr in which case the distance will be lost. | |
| * | |
| * @return The closest coordinate. | |
| */ | |
| virtual RS_Vector getNearestPointOnEntity( | |
| const RS_Vector & /*coord*/, | |
| bool onEntity = true, double *dist = nullptr, | |
| RS_Entity **entity = nullptr) const = 0; | |
| /** | |
| * Must be overwritten to get the (nearest) center point to the | |
| * given coordinate for this entity. | |
| * | |
| * @param coord Coordinate (typically a mouse coordinate) | |
| * @param dist Pointer to a value which will contain the measured | |
| * distance between 'coord' and the closest center point. The passed | |
| * pointer can also be nullptr in which case the distance will be | |
| * lost. | |
| * | |
| * @return The closest center point. | |
| */ | |
| virtual RS_Vector getNearestCenter( | |
| const RS_Vector &coord, | |
| double *dist = nullptr) const = 0; | |
| /** | |
| * Must be overwritten to get the (nearest) middle point to the | |
| * given coordinate for this entity. | |
| * | |
| * @param coord Coordinate (typically a mouse coordinate) | |
| * @param dist Pointer to a value which will contain the measured | |
| * distance between 'coord' and the closest middle point. The passed | |
| * pointer can also be nullptr in which case the distance will be | |
| * lost. | |
| * | |
| * @return The closest middle point. | |
| */ | |
| virtual RS_Vector getMiddlePoint(void) const{ | |
| return RS_Vector(false); | |
| } | |
| virtual RS_Vector getNearestMiddle( | |
| const RS_Vector &coord, | |
| double *dist = nullptr, | |
| int middlePoints = 1 | |
| ) const = 0; | |
| /** | |
| * Must be overwritten to get the nearest point with a given | |
| * distance to the endpoint to the given coordinate for this entity. | |
| * | |
| * @param distance Distance to endpoint. | |
| * @param coord Coordinate (typically a mouse coordinate) | |
| * @param dist Pointer to a value which will contain the measured | |
| * distance between 'coord' and the closest point. The passed | |
| * pointer can also be nullptr in which case the distance will be | |
| * lost. | |
| * | |
| * @return The closest point with the given distance to the endpoint. | |
| */ | |
| virtual RS_Vector getNearestDist( | |
| double distance, | |
| const RS_Vector &coord, | |
| double *dist = nullptr) const = 0; | |
| /** | |
| * Must be overwritten to get the point with a given | |
| * distance to the start- or endpoint to the given coordinate for this entity. | |
| * | |
| * @param distance Distance to endpoint. | |
| * @param startp true = measured from Startpoint, false = measured from Endpoint | |
| * | |
| * @return The point with the given distance to the start- or endpoint. | |
| */ | |
| virtual RS_Vector getNearestDist( | |
| double /*distance*/, | |
| bool /*startp*/) const{ | |
| return RS_Vector(false); | |
| } | |
| /** | |
| * @brief dualLineTangentPoint find the tangent point for a line in line coordinates | |
| * @param line a tangent line in line coordinates | |
| * @return the tangent point for the line | |
| */ | |
| virtual RS_Vector dualLineTangentPoint([[maybe_unused]] const RS_Vector &line) const{ | |
| return RS_Vector{false}; | |
| } | |
| /** | |
| * Must be overwritten to get the nearest reference point for this entity. | |
| * | |
| * @param coord Coordinate (typically a mouse coordinate) | |
| * @param dist Pointer to a value which will contain the measured | |
| * distance between 'coord' and the closest point. The passed | |
| * pointer can also be nullptr in which case the distance will be | |
| * lost. | |
| * | |
| * @return The closest point with the given distance to the endpoint. | |
| */ | |
| virtual RS_Vector getNearestRef( | |
| const RS_Vector &coord, | |
| double *dist = nullptr) const; | |
| /** | |
| * Gets the nearest reference point of this entity if it is selected. | |
| * Containers re-implement this method to return the nearest reference | |
| * point of a selected sub entity. | |
| * | |
| * @param coord Coordinate (typically a mouse coordinate) | |
| * @param dist Pointer to a value which will contain the measured | |
| * distance between 'coord' and the closest point. The passed | |
| * pointer can also be nullptr in which case the distance will be | |
| * lost. | |
| * | |
| * @return The closest point with the given distance to the endpoint. | |
| */ | |
| virtual RS_Vector getNearestSelectedRef( | |
| const RS_Vector &coord, | |
| double *dist = nullptr) const; | |
| /** | |
| * Must be overwritten to get the shortest distance between this | |
| * entity and a coordinate. | |
| * | |
| * @param coord Coordinate (typically a mouse coordinate) | |
| * @param entity Pointer which will contain the (sub-)entity which is | |
| * closest to the given point or nullptr if the caller is not | |
| * interested in this information. | |
| * @param level The resolve level. | |
| * | |
| * @sa RS2::ResolveLevel | |
| * | |
| * @return The measured distance between \p coord and the entity. | |
| */ | |
| virtual RS_Vector getNearestOrthTan( | |
| const RS_Vector & /*coord*/, | |
| const RS_Line & /*normal*/, | |
| bool onEntity = false) const; | |
| virtual double getDistanceToPoint( | |
| const RS_Vector &coord, | |
| RS_Entity **entity = nullptr, | |
| RS2::ResolveLevel level = RS2::ResolveNone, | |
| double solidDist = RS_MAXDOUBLE) const; | |
| virtual bool isPointOnEntity( | |
| const RS_Vector &coord, | |
| double tolerance = 20. * RS_TOLERANCE) const; | |
| /** | |
| * Implementations must offset the entity by the given direction and distance. | |
| */ | |
| virtual bool offset(const RS_Vector & /*coord*/, const double & /*distance*/){return false;} | |
| /** | |
| * Implementations must offset the entity by the distance at both directions | |
| * used to generate tangential circles | |
| */ | |
| virtual std::vector<RS_Entity *> offsetTwoSides(const double & /*distance*/) const{ | |
| return std::vector<RS_Entity *>(); | |
| } | |
| /** | |
| * implementations must revert the direction of an atomic entity | |
| */ | |
| virtual void revertDirection(){} | |
| /** | |
| * Implementations must move the entity by the given vector. | |
| */ | |
| virtual void move(const RS_Vector &offset) = 0; | |
| /** | |
| * Implementations must rotate the entity by the given angle around | |
| * the given center. | |
| */ | |
| virtual void rotate(const RS_Vector ¢er, double angle) = 0; | |
| virtual void rotate(const RS_Vector ¢er, const RS_Vector &angleVector) = 0; | |
| /** | |
| * Implementations must scale the entity by the given factors. | |
| */ | |
| virtual void scale(const RS_Vector ¢er, const RS_Vector &factor) = 0; | |
| /** | |
| * Acts like scale(RS_Vector) but with equal factors. | |
| * Equal to scale(center, RS_Vector(factor, factor)). | |
| */ | |
| virtual void scale(const RS_Vector ¢er, const double &factor){ | |
| scale(center, RS_Vector(factor, factor)); | |
| } | |
| virtual void scale(const RS_Vector &factor){ | |
| scale(RS_Vector(0., 0.), factor); | |
| } | |
| /** | |
| * Implementations must mirror the entity by the given axis. | |
| */ | |
| virtual void mirror(const RS_Vector &axisPoint1, const RS_Vector &axisPoint2) = 0; | |
| virtual void stretch( | |
| const RS_Vector &firstCorner, | |
| const RS_Vector &secondCorner, | |
| const RS_Vector &offset); | |
| /** | |
| * @description: Implementation of the Shear/Skew the entity | |
| * The shear transform is | |
| * 1 k 0 | |
| * 0 1 0 | |
| * 1 | |
| * @author Dongxu Li | |
| * @param[in] double - k the skew/shear parameter | |
| */ | |
| virtual RS_Entity &shear(double k) = 0; | |
| /** | |
| * @description: Implementation of the Shear/Skew the entity | |
| * The shear transform is | |
| * 1 k 0 | |
| * 0 1 0 | |
| * 1 | |
| * @author Dongxu Li | |
| * @param[in] const RS_Vector& - origin the point to be used as the origin | |
| * @param[in] const RS_Vector& - the x-axis direction | |
| * @param[in] double - k the skew/shear parameter | |
| */ | |
| virtual RS_Entity &shear(const RS_Vector &origin, const RS_Vector &xAxis, double k){ | |
| rotate(origin, -xAxis.angle()); | |
| move(-origin); | |
| shear(k); | |
| move(origin); | |
| rotate(origin, xAxis.angle()); | |
| return *this; | |
| } | |
| /** | |
| * Implementations must drag the reference point(s) of all | |
| * (sub-)entities that are very close to ref by offset. | |
| */ | |
| virtual void moveRef( | |
| const RS_Vector & /*ref*/, | |
| const RS_Vector & /*offset*/){ | |
| return; | |
| } | |
| /** | |
| * Implementations must drag the reference point(s) of selected | |
| * (sub-)entities that are very close to ref by offset. | |
| */ | |
| virtual void moveSelectedRef( | |
| const RS_Vector & /*ref*/, | |
| const RS_Vector & /*offset*/){ | |
| return; | |
| } | |
| virtual void drawAsChild(RS_Painter *painter){ | |
| draw(painter); | |
| } | |
| virtual void drawDraft(RS_Painter *painter) { | |
| draw(painter); | |
| }; | |
| // double getStyleFactor(RS_GraphicView *view); | |
| QString getUserDefVar(const QString &key) const; | |
| std::vector<QString> getAllKeys() const; | |
| void setUserDefVar(QString key, QString val); | |
| void delUserDefVar(QString key); | |
| friend std::ostream &operator<<(std::ostream &os, RS_Entity &e); | |
| /** Recalculates the borders of this entity. */ | |
| virtual void calculateBorders() = 0; | |
| /** whether the entity is on a constructionLayer */ | |
| //! constructionLayer contains entities of infinite length, constructionLayer doesn't show up in print | |
| bool isConstruction(bool typeCheck = false) const; // ignore certain entity types for constructionLayer check | |
| //! whether printing is enabled or disabled for the entity's layer | |
| bool isPrint(void) const; | |
| /** return the equation of the entity | |
| for quadratic, | |
| return a vector contains: | |
| m0 x^2 + m1 xy + m2 y^2 + m3 x + m4 y + m5 =0 | |
| for linear: | |
| m0 x + m1 y + m2 =0 | |
| **/ | |
| virtual LC_Quadratic getQuadratic() const; | |
| /** | |
| * @brief areaLineIntegral, line integral for contour area calculation by Green's Theorem | |
| * Contour Area =\oint x dy | |
| * @return line integral \oint x dy along the entity | |
| */ | |
| virtual double areaLineIntegral() const; | |
| /** | |
| * @brief trimmable, whether the entity type can be trimmed | |
| * @return true, for trimmable entity types | |
| * currently, trimmable types are: RS_Line, RS_Circle, RS_Arc, RS_Ellipse | |
| */ | |
| bool trimmable() const; | |
| /** | |
| * @brief isArc is the entity of type Arc, Circle, or Ellipse | |
| * @return true for Arc, Circle, or Ellipse | |
| */ | |
| virtual bool isArc() const; | |
| /** | |
| * @brief isArcLine determine the entity is either Arc, Circle, or Line | |
| * @return true if entity is Arc, Circle, or Line | |
| */ | |
| virtual bool isArcCircleLine() const; | |
| bool isParentIgnoredOnModifications() const; | |
| protected: | |
| //! Entity's parent entity or nullptr is this entity has no parent. | |
| RS_EntityContainer *parent = nullptr; | |
| //! minimum coordinates | |
| RS_Vector minV; | |
| //! maximum coordinates | |
| RS_Vector maxV; | |
| //! Pointer to layer | |
| RS_Layer *m_layer = nullptr; | |
| //! auto updating enabled? | |
| bool updateEnabled = false; | |
| void init(bool setPenAndLayerToActive); | |
| void initId(); | |
| private: | |
| //! Entity m_id | |
| unsigned long long m_id = 0; | |
| // pImp to delay pulling in Qt headers | |
| struct Impl; | |
| std::unique_ptr<Impl> m_pImpl; | |
| }; | |