1 /*************************************************************************** 2 qgsmeshforcebypolylines.h - QgsMeshForceByPolylines 3 4 --------------------- 5 begin : 5.9.2021 6 copyright : (C) 2021 by Vincent Cloarec 7 email : vcloarec at gmail dot com 8 *************************************************************************** 9 * * 10 * This program is free software; you can redistribute it and/or modify * 11 * it under the terms of the GNU General Public License as published by * 12 * the Free Software Foundation; either version 2 of the License, or * 13 * (at your option) any later version. * 14 * * 15 ***************************************************************************/ 16 #ifndef QGSMESHFORCEBYPOLYLINES_H 17 #define QGSMESHFORCEBYPOLYLINES_H 18 19 20 #include "qgis_core.h" 21 #include "qgstopologicalmesh.h" 22 #include "qgstriangularmesh.h" 23 #include "qgsabstractgeometry.h" 24 #include "qgsmeshadvancedediting.h" 25 26 /** 27 * \ingroup core 28 * 29 * \brief Class derived from QgsMeshAdvancedEditing that forces mesh based on a line 30 * 31 * Forcing lines consist of line that the faces are forced to follow, that is edges of encountered faces have to be on theses lines. 32 * 33 * Caller of this class has to set the line with setInputLine() before applying the edition with QgsMeshEditor::advancedEdit() 34 * 35 * Other option has also to be set before calling QgsMeshEditor::advancedEdit() 36 * 37 * \since QGIS 3.22 38 */ 39 class CORE_EXPORT QgsMeshEditForceByLine : public QgsMeshAdvancedEditing 40 { 41 public: 42 43 //! Constructor 44 QgsMeshEditForceByLine() = default; 45 46 //! Sets the input forcing line in rendering coordinates 47 void setInputLine( const QgsPoint &pt1, const QgsPoint &pt2, double tolerance, bool newVertexOnIntersection ); 48 49 //! Sets the tolerance in redering coordinate system unit 50 void setTolerance( double tolerance ); 51 52 //! Sets whether vertices will be added when the lines will intersect internal edges of faces, default is FALSE 53 void setAddVertexOnIntersection( bool addVertex ); 54 55 //! Sets the default value of Z coordinate to use for new vertices, this value will be used if the Z value 56 void setDefaultZValue( double defaultZValue ); 57 58 /** 59 * Sets whether the new created vertices will have their value interpolated from the existing mesh. 60 * If not, Z value will be interpolated from the lines, 61 * in case these line are not 3D, the default value will be used (\see setDefaultZValue()) 62 */ 63 void setInterpolateZValueOnMesh( bool interpolateZValueOnMesh ); 64 65 private: 66 QgsPoint mPoint1; 67 QgsPoint mPoint2; 68 bool mNewVertexOnIntersection = false; 69 double mTolerance = 1e-8; 70 double mDefaultZValue = 0; 71 bool mInterpolateZValueOnMesh = false; 72 73 QgsTopologicalMesh::Changes apply( QgsMeshEditor *meshEditor ) override; 74 75 virtual void finish(); 76 77 //members and method used for the calculation 78 QgsMeshEditor *mEditor = nullptr; 79 QList<int> mRemovedFaces; 80 QList<int> mHoleOnLeft; // contains the border vertices of hole to fill on the right of the line (line go up) 81 QList<int> mNeighborOnLeft; //contains the neighbor face on the right of the line (line go up) 82 QList<int> mHoleOnRight; // contains the border vertices of hole to fill on the right of the line (line go up) 83 QList<int> mNeighborOnRight; // contains the neighbor face on the right of the line (line go up) 84 QList<int> mNewVerticesIndexesOnLine; //the new vertices intersecting edges except 85 bool mEndOnPoint2 = false; 86 int mPoint2VertexIndex = -1; 87 int mCurrentSnappedVertex = -1; // Last snapped point 88 QgsPoint mCurrentPointPosition; 89 90 bool mFirstPointChecked = false; 91 bool mSecondPointChecked = false; 92 93 void interpolateZValueOnMesh( QgsPoint &point ) const; 94 void interpolateZValueOnMesh( int faceIndex, QgsPoint &point ) const; 95 void interpolateZValue( QgsMeshVertex &point, const QgsPoint &otherPoint1, const QgsPoint &otherPoint2 ); 96 97 98 bool buildForcedElements(); 99 100 bool edgeIntersection( int vertex1, 101 int vertex2, 102 int &closestSnappedVertex, 103 QgsPoint &intersectionPoint, 104 bool outAllowed ); 105 106 bool searchIntersectionEdgeFromSnappedVertex( 107 int &intersectionFaceIndex, 108 int &previousSnappedVertex, 109 int ¤tSnappedVertexIndex, 110 QgsPoint &intersectionPoint, 111 int &edgePosition, 112 QSet<int> &treatedFaces ); 113 114 // Insert a new vertex and returns its local index (0 is first index in th 115 int insertNewVertex( const QgsMeshVertex &vertex ); 116 117 bool triangulateHoles( const QList<int> &holeOnLeft, 118 const QList<int> &neighborOnLeft, 119 bool isLeftHole, 120 QList<std::array<int, 2> > &newFacesOnLine, 121 std::array<int, 2> &extremeFaces ); 122 123 bool finishForcingLine(); 124 125 friend class TestQgsMeshEditor; 126 friend class QgsMeshEditForceByPolylines; 127 }; 128 129 130 131 /** 132 * \ingroup core 133 * 134 * \brief Class derived from QgsMeshEditForceByLine that forces mesh based on polyline. 135 * 136 * Forcing lines consist of line that the faces are forced to follow, that is edges of encountered faces have to be on theses lines. 137 * 138 * Caller of this class has to add the lines from QgsGeometry instances with addLineFromGeometry() or addLinesFromGeometries() 139 * before applying the edition with QgsMeshEditor::advancedEdit() 140 * 141 * 142 * \since QGIS 3.22 143 */ 144 class CORE_EXPORT QgsMeshEditForceByPolylines : public QgsMeshEditForceByLine 145 { 146 public: 147 148 //! Constructor 149 QgsMeshEditForceByPolylines() = default; 150 151 QString text() const override; 152 bool isFinished() const override; 153 154 /** 155 * Adds a input forcing line geometry in rendering coordinates 156 * 157 * \note if the geometry is not 3D, the default Z value will be used for the Z value of the geometry's vertices. 158 * This default Z value has to be set before adding the geometry (\see setDefaultZValue() 159 */ 160 void addLineFromGeometry( const QgsGeometry &geom ); 161 162 /** 163 * Adds a list of input forcing lines geometry in rendering coordinates 164 * 165 * \note if the geometry is not 3D, the default Z value will be used for the Z value of the geometry's vertices. 166 * This default Z value has to be set before adding the geometry (\see setDefaultZValue() 167 */ 168 void addLinesFromGeometries( const QList<QgsGeometry> geometries ); 169 170 private: 171 QList<QgsPointSequence> mPolylines; 172 int mCurrentPolyline = 0; 173 int mCurrentSegment = 0; 174 175 void incrementSegment(); 176 177 using QgsMeshEditForceByLine::setInputLine; 178 QgsTopologicalMesh::Changes apply( QgsMeshEditor *meshEditor ) override; 179 180 }; 181 182 #endif // QGSMESHFORCEBYPOLYLINES_H 183