File size: 12,308 Bytes
a5ffdcd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | /****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** 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!
**
**********************************************************************/
#ifndef RS_ENTITYCONTAINER_H
#define RS_ENTITYCONTAINER_H
#include <QList>
#include "rs_entity.h"
/**
* Class representing a tree of entities.
* Typical entity containers are graphics, polylines, groups, texts, ...)
*
* @author Andrew Mustun
*/
class RS_EntityContainer : public RS_Entity {
public:
using value_type = RS_Entity * ;
struct RefInfo{
RS_Vector ref;
RS_Entity* entity = nullptr;
};
struct LC_SelectionInfo{
unsigned count = 0;
double length = 0.0;
};
RS_EntityContainer(RS_EntityContainer* parent=nullptr, bool owner=true);
RS_EntityContainer(const RS_EntityContainer& other);
RS_EntityContainer(const RS_EntityContainer& other, bool copyChildren);
RS_EntityContainer& operator = (const RS_EntityContainer& other);
RS_EntityContainer(RS_EntityContainer&& other);
RS_EntityContainer& operator = (RS_EntityContainer&& other);
//RS_EntityContainer(const RS_EntityContainer& ec);
~RS_EntityContainer() override;
RS_Entity* clone() const override;
virtual void detach();
/** @return RS2::EntityContainer */
RS2::EntityType rtti() const override{
return RS2::EntityContainer;
}
void reparent(RS_EntityContainer* parent) override;
/**
* @return true: because entities made from this class
* and subclasses are containers for other entities.
*/
bool isContainer() const override{
return true;
}
/**
* @return false: because entities made from this class
* and subclasses are containers for other entities.
*/
bool isAtomic() const override{
return false;
}
double getLength() const override;
void setVisible(bool v) override;
bool setSelected(bool select=true) override;
bool toggleSelected() override;
void setHighlighted(bool on) override;
/*virtual void selectWindow(RS_Vector v1, RS_Vector v2,
bool select=true, bool cross=false);*/
virtual void selectWindow(enum RS2::EntityType typeToSelect, RS_Vector v1, RS_Vector v2,
bool select=true, bool cross=false);
virtual void selectWindow(const QList<RS2::EntityType> &typesToSelect, RS_Vector v1, RS_Vector v2,
bool select=true, bool cross=false);
virtual void addEntity(RS_Entity* entity);
virtual void appendEntity(RS_Entity* entity);
virtual void prependEntity(RS_Entity* entity);
virtual void moveEntity(int index, QList<RS_Entity *>& entList);
void adjustBordersIfNeeded(RS_Entity* entity);
virtual void insertEntity(int index, RS_Entity* entity);
virtual bool removeEntity(RS_Entity* entity);
//!
//! \brief addRectangle add four lines to form a rectangle by
//! the diagonal vertices v0,v1
//! \param v0,v1 diagonal vertices of the rectangle
//!
void addRectangle(RS_Vector const& v0, RS_Vector const& v1);
void addRectangle(RS_Vector const& v0, RS_Vector const& v1,RS_Vector const& v2, RS_Vector const& v3);
virtual RS_Entity* firstEntity(RS2::ResolveLevel level=RS2::ResolveNone) const;
virtual RS_Entity* lastEntity(RS2::ResolveLevel level=RS2::ResolveNone) const;
virtual RS_Entity* nextEntity(RS2::ResolveLevel level=RS2::ResolveNone) const;
virtual RS_Entity* prevEntity(RS2::ResolveLevel level=RS2::ResolveNone) const;
virtual RS_Entity* entityAt(int index) const;
virtual void setEntityAt(int index,RS_Entity* en);
virtual int findEntity(RS_Entity const* const entity);
int findEntityIndex(RS_Entity const* const entity);
bool areNeighborsEntities(RS_Entity const *const e1, RS_Entity const *const e2);
virtual void clear();
//virtual unsigned long int count() {
// return count(false);
//}
virtual bool isEmpty() const {
return count()==0;
}
bool empty() const {
return isEmpty();
}
unsigned count() const override;
unsigned countDeep() const override;
size_t size() const
{
return m_entities.size();
}
//virtual unsigned long int countLayerEntities(RS_Layer* layer);
/** \brief countSelected number of selected
* @param deep count sub-containers, if true
* @param types if is not empty, only counts by types listed
*/
virtual unsigned countSelected(bool deep=true, QList<RS2::EntityType> const& types = {});
virtual void collectSelected(std::vector<RS_Entity*> &collect, bool deep, QList<RS2::EntityType> const &types = {});
virtual double totalSelectedLength();
LC_SelectionInfo getSelectionInfo(/*bool deep, */QList<RS2::EntityType> const& types = {});
/**
* Enables / disables automatic update of borders on entity removals
* and additions. By default this is turned on.
*/
void setAutoUpdateBorders(bool enable) {
m_autoUpdateBorders = enable;
}
bool getAutoUpdateBorders() const {
return m_autoUpdateBorders;
}
virtual void adjustBorders(RS_Entity* entity);
void calculateBorders() override;
void forcedCalculateBorders();
int updateDimensions( bool autoText=true);
int updateVisibleDimensions( bool autoText=true);
virtual void updateInserts();
virtual void updateSplines();
void update() override;
virtual void renameInserts(const QString& oldName,
const QString& newName);
RS_Vector getNearestEndpoint(const RS_Vector& coord,
double* dist = nullptr)const override;
RS_Vector getNearestEndpoint(const RS_Vector& coord,
double* dist, RS_Entity** pEntity ) const;
RS_Entity* getNearestEntity(const RS_Vector& point,
double* dist = nullptr,
RS2::ResolveLevel level=RS2::ResolveAll) const;
RS_Vector getNearestPointOnEntity(const RS_Vector& coord,
bool onEntity = true,
double* dist = nullptr,
RS_Entity** entity=nullptr)const override;
RS_Vector getNearestCenter(const RS_Vector& coord,
double* dist = nullptr)const override;
RS_Vector getNearestMiddle(const RS_Vector& coord,
double* dist = nullptr,
int middlePoints = 1
)const override;
RS_Vector getNearestDist(double distance,
const RS_Vector& coord,
double* dist = nullptr) const override;
RS_Vector getNearestIntersection(const RS_Vector& coord,
double* dist = nullptr);
RS_Vector getNearestVirtualIntersection(const RS_Vector& coord,
const double& angle,
double* dist);
RS_Vector getNearestRef(const RS_Vector& coord,
double* dist = nullptr) const override;
RS_Vector getNearestSelectedRef(const RS_Vector& coord,
double* dist = nullptr) const override;
RefInfo getNearestSelectedRefInfo(const RS_Vector& coord,
double* dist = nullptr) const;
double getDistanceToPoint(const RS_Vector& coord,
RS_Entity** entity,
RS2::ResolveLevel level=RS2::ResolveNone,
double solidDist = RS_MAXDOUBLE) const override;
virtual bool optimizeContours();
bool hasEndpointsWithinWindow(const RS_Vector& v1, const RS_Vector& v2) const override;
void move(const RS_Vector& offset) override;
void rotate(const RS_Vector& center, double angle) override;
void rotate(const RS_Vector& center, const RS_Vector& angleVector) override;
void scale(const RS_Vector& center, const RS_Vector& factor) override;
void mirror(const RS_Vector& axisPoint1, const RS_Vector& axisPoint2a) override;
RS_Entity& shear(double k) override;
void stretch(const RS_Vector& firstCorner,
const RS_Vector& secondCorner,
const RS_Vector& offset) override;
void calculateBordersIfNeeded();
void moveRef(const RS_Vector& ref, const RS_Vector& offset) override;
void moveSelectedRef(const RS_Vector& ref, const RS_Vector& offset) override;
void revertDirection() override;
void draw(RS_Painter* painter) override;
friend std::ostream& operator << (std::ostream& os, RS_EntityContainer& ec);
bool isOwner() const {return autoDelete;}
void setOwner(bool owner) {autoDelete=owner;}
/**
* @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
* returns absolute value
*/
double areaLineIntegral() const override;
/**
* @brief ignoreForModification ignore this entity for entity catch for certain actions
* like catching circles to create tangent circles
* @return, true, indicate this entity container should be ignored
*/
bool ignoredOnModification() const;
void push_back(RS_Entity* entity) {
m_entities.push_back(entity);
}
void pop_back() {
if (!isEmpty())
m_entities.pop_back();
}
/**
* @brief begin/end to support range based loop
* @return iterator
*/
QList<RS_Entity *>::const_iterator begin() const;
QList<RS_Entity *>::const_iterator end() const;
QList<RS_Entity *>::const_iterator cbegin() const;
QList<RS_Entity *>::const_iterator cend() const;
QList<RS_Entity *>::iterator begin() ;
QList<RS_Entity *>::iterator end() ;
//! \{
//! first and last without resolving into children, assume the container is
//! not empty
RS_Entity* last() const;
RS_Entity* first() const;
//! \}
const QList<RS_Entity*>& getEntityList();
inline RS_Entity* unsafeEntityAt(int index) const {return m_entities.at(index);}
void drawAsChild(RS_Painter *painter) override;
RS_Entity *cloneProxy() const override;
protected:
/**
* @brief getLoops for hatch, split closed loops into single simple loops. All returned containers are owned by
* the returned object.
* @return std::vector<std::unique_ptr<RS_EntityContainer>> - each container contains edge entities of a single
* closed loop. Each loop is assumed to be simply closed, and loops never cross each other.
*/
virtual std::vector<std::unique_ptr<RS_EntityContainer>> getLoops() const;
/** sub container used only temporarily for iteration. */
mutable RS_EntityContainer* subContainer = nullptr;
private:
/**
* @brief ignoredSnap whether snapping is ignored
* @return true when entity of this container won't be considered for snapping points
*/
bool ignoredSnap() const;
/** m_entities in the container */
QList<RS_Entity *> m_entities;
/**
* Automatically update the borders of the container when entities
* are added or removed.
*/
bool m_autoUpdateBorders = true;
mutable int entIdx = 0;
bool autoDelete = false;
};
#endif
|