1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0.txt 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 *=========================================================================*/ 18 #ifndef itkGeometricalQuadEdge_h 19 #define itkGeometricalQuadEdge_h 20 21 #include "itkQuadEdge.h" 22 23 namespace itk 24 { 25 /** \class GeometricalQuadEdge 26 * \brief This class extends the QuadEdge by adding a reference to the Origin. 27 * 28 * The class is implemented in such a way that it can generate its own Dual. 29 * In a physical edge, there will be four GeometricalQuadEdge. Two of them will 30 * be Primal and two will be Dual. The Primal ones are parallel to the physical 31 * edge and their origins relate to the mesh points. The Dual ones are 32 * orthogonal to the physical edge and their origins relate to the faces at 33 * each side of the physical edge. 34 * 35 * The only purpose of the last paramater of the template is to guarantee that 36 * the two types GeometricalQuadEdge and GeometricalQuadEdge::Dual 37 * are always different (in the sense that their typeid() are different). If 38 * we only had the four first parameters and assume that 39 * GeometricalQuadEdge gets instantiated with types such that TVRef = 40 * TFRef and TPrimalData = TDualData then this instantiation 41 * GeometricalQuadEdge and GeometricalQuadEdge::Dual would be the 42 * same types (this is simply due to the very definition of 43 * GeometricalQuadEdge::Dual). This would in turn make the types QEType 44 * and QEDual of \ref QuadEdgeMesh identical and would prevent any algorithm 45 * requiring to distinguish those types (e.g. by relying on a 46 * dynamic_cast<QEType*>) to be effective. This justifies the existence of 47 * last dummy template parameter and it's default value. 48 * 49 * \author Alexandre Gouaillard, Leonardo Florez-Valencia, Eric Boix 50 * 51 * This implementation was contributed as a paper to the Insight Journal 52 * https://hdl.handle.net/1926/306 53 * 54 * \sa QuadEdge 55 * 56 * \ingroup MeshObjects 57 * \ingroup ITKQuadEdgeMesh 58 */ 59 template< typename TVRef, typename TFRef, 60 typename TPrimalData, typename TDualData, 61 bool PrimalDual = true > 62 class ITK_TEMPLATE_EXPORT GeometricalQuadEdge:public QuadEdge 63 { 64 public: 65 /** Hierarchy type alias. */ 66 using Self = GeometricalQuadEdge; 67 using Superclass = QuadEdge; 68 using RawPointer = Self *; 69 70 /** 71 * Dual type, basically the same type with swapped template 72 * parameters. 73 * 74 */ 75 using DualType = GeometricalQuadEdge< TFRef, TVRef, 76 TDualData, TPrimalData, !PrimalDual >; 77 78 /** Input template parameters & values convenient renaming. */ 79 using OriginRefType = TVRef; 80 using DualOriginRefType = TFRef; 81 using PrimalDataType = TPrimalData; 82 using DualDataType = TDualData; 83 // Line Cell Id in Mesh Cell Container 84 // used to go up to LineCell level 85 using LineCellIdentifier = TFRef; 86 87 public: 88 89 /** Iterator types. */ 90 using IteratorGeom = QuadEdgeMeshIteratorGeom< Self >; 91 using ConstIteratorGeom = QuadEdgeMeshConstIteratorGeom< Self >; 92 93 /** Basic iterators methods. */ 94 inline itkQEDefineIteratorGeomMethodsMacro(Onext); 95 inline itkQEDefineIteratorGeomMethodsMacro(Sym); 96 inline itkQEDefineIteratorGeomMethodsMacro(Lnext); 97 inline itkQEDefineIteratorGeomMethodsMacro(Rnext); 98 inline itkQEDefineIteratorGeomMethodsMacro(Dnext); 99 inline itkQEDefineIteratorGeomMethodsMacro(Oprev); 100 inline itkQEDefineIteratorGeomMethodsMacro(Lprev); 101 inline itkQEDefineIteratorGeomMethodsMacro(Rprev); 102 inline itkQEDefineIteratorGeomMethodsMacro(Dprev); 103 inline itkQEDefineIteratorGeomMethodsMacro(InvOnext); 104 inline itkQEDefineIteratorGeomMethodsMacro(InvLnext); 105 inline itkQEDefineIteratorGeomMethodsMacro(InvRnext); 106 inline itkQEDefineIteratorGeomMethodsMacro(InvDnext); 107 108 /** QE macros. */ 109 itkQEAccessorsMacro(Superclass, Self, DualType); 110 111 public: 112 GeometricalQuadEdge(); 113 GeometricalQuadEdge(const GeometricalQuadEdge &) = default; 114 GeometricalQuadEdge(GeometricalQuadEdge &&) = default; 115 GeometricalQuadEdge & operator=(const GeometricalQuadEdge &) = default; 116 GeometricalQuadEdge & operator=(GeometricalQuadEdge &&) = default; 117 virtual ~GeometricalQuadEdge() override = default; 118 119 /** Set methods. */ SetOrigin(const OriginRefType v)120 inline void SetOrigin(const OriginRefType v) 121 { m_Origin = v; } 122 SetDestination(const OriginRefType v)123 inline void SetDestination(const OriginRefType v) 124 { this->GetSym()->SetOrigin(v); } 125 SetRight(const DualOriginRefType v)126 inline void SetRight(const DualOriginRefType v) 127 { this->GetRot()->SetOrigin(v); } 128 SetLeft(const DualOriginRefType v)129 inline void SetLeft(const DualOriginRefType v) 130 { this->GetInvRot()->SetOrigin(v); } 131 132 /** 133 * Set the Left() of all the edges in the Lnext() ring of "this" 134 * with the same given geometrical information. 135 * @param faceGeom Looks at most maxSize edges in the Lnext() ring. 136 * @param maxSize Sets at most maxSize edges in the Lnext() ring. 137 * @return Returns true on success. False otherwise. 138 */ 139 bool SetLnextRingWithSameLeftFace(const DualOriginRefType faceGeom, 140 int maxSize = 100); 141 UnsetOrigin()142 inline void UnsetOrigin() { m_Origin = m_NoPoint; } UnsetDestination()143 inline void UnsetDestination() { this->GetSym()->UnsetOrigin(); } UnsetRight()144 inline void UnsetRight() { this->GetRot()->UnsetOrigin(); } UnsetLeft()145 inline void UnsetLeft() { this->GetInvRot()->UnsetOrigin(); } 146 147 /** Get methods. */ 148 //ORIENTATION_NOTE: this definition of GetLeft (or GetRight) 149 // implicitely assumes that the Onext order is counter-clockwise ! GetOrigin()150 inline const OriginRefType GetOrigin() const { return ( m_Origin ); } GetDestination()151 inline const OriginRefType GetDestination() const { return ( GetSym()->GetOrigin() ); } GetRight()152 inline const DualOriginRefType GetRight() const { return ( GetRot()->GetOrigin() ); } GetLeft()153 inline const DualOriginRefType GetLeft() const { return ( GetInvRot()->GetOrigin() ); } 154 155 /** Boolean accessors. */ 156 bool IsOriginSet() const; 157 158 bool IsDestinationSet() const; 159 160 bool IsRightSet() const; 161 162 bool IsLeftSet() const; 163 164 /** Extra data set methods. */ SetPrimalData(const PrimalDataType data)165 inline void SetPrimalData(const PrimalDataType data) 166 { m_Data = data; this->SetPrimalData(); } SetDualData(const DualDataType data)167 inline void SetDualData(const DualDataType data) 168 { this->GetRot()->SetPrimalData(data); } 169 SetPrimalData()170 inline void SetPrimalData() { m_DataSet = true; } SetDualData()171 inline void SetDualData() { this->GetRot()->SetPrimalData(); } 172 UnsetPrimalData()173 inline void UnsetPrimalData() { m_Data = false; } UnsetDualData()174 inline void UnsetDualData() { this->GetRot()->UnsetPrimalData(); } 175 176 /** Extra data get methods. */ GetPrimalData()177 inline PrimalDataType GetPrimalData() { return ( m_Data ); } GetDualData()178 inline DualDataType GetDualData() 179 { return ( this->GetRot()->GetPrimalData() ); } 180 181 /** Boolean accessors. */ IsPrimalDataSet()182 inline bool IsPrimalDataSet() { return ( m_DataSet ); } IsDualDataSet()183 inline bool IsDualDataSet() 184 { return ( this->GetRot()->IsPrimalDataSet() ); } 185 186 /** 187 * @return Returns true when "this" has no faces set on both sides. 188 * Return false otherwise. 189 */ IsWire()190 inline bool IsWire() 191 { return ( !( this->IsLeftSet() ) && !( this->IsRightSet() ) ); } 192 193 /** 194 * @return Returns true when "this" is on the boundary i.e. 195 * one and only one of the faces is set. Return false 196 * otherwise. 197 */ IsAtBorder()198 inline bool IsAtBorder() 199 { 200 return ( ( this->IsLeftSet() && !this->IsRightSet() ) 201 || ( !this->IsLeftSet() && this->IsRightSet() ) ); 202 } 203 204 /** 205 * @return Returns true when "this" has faces set on both sides. 206 * Return false otherwise. 207 */ IsInternal()208 inline bool IsInternal() const 209 { return ( this->IsLeftSet() && this->IsRightSet() ); } 210 211 bool IsOriginInternal() const; 212 213 bool IsLnextSharingSameFace(int maxSize = 100); 214 215 bool IsLnextOfTriangle(); 216 217 bool IsInOnextRing(Self *); 218 219 bool IsInLnextRing(Self *); 220 221 Self * GetNextBorderEdgeWithUnsetLeft(Self *edgeTest = nullptr); 222 223 bool InsertAfterNextBorderEdgeWithUnsetLeft(Self *isol, 224 Self *hint = nullptr); 225 226 bool ReorderOnextRingBeforeAddFace(Self *second); 227 228 /** Disconnection methods. */ IsOriginDisconnected()229 inline bool IsOriginDisconnected() 230 { return ( this == this->GetOnext() ); } IsDestinationDisconnected()231 inline bool IsDestinationDisconnected() 232 { return ( this->GetSym()->IsOriginDisconnected() ); } IsDisconnected()233 inline bool IsDisconnected() 234 { 235 return ( this->IsOriginDisconnected() 236 && this->IsDestinationDisconnected() ); 237 } 238 239 void Disconnect(); 240 SetIdent(const LineCellIdentifier & User_Value)241 inline void SetIdent(const LineCellIdentifier & User_Value) { this->m_LineCellIdent = User_Value; } GetIdent()242 inline LineCellIdentifier GetIdent() { return ( this->m_LineCellIdent ); } 243 244 public: 245 // Reserved OriginRefType designated to represent the absence of Origin 246 static const OriginRefType m_NoPoint; 247 248 protected: 249 OriginRefType m_Origin; // Geometrical information 250 PrimalDataType m_Data; // User data associated to this edge. 251 bool m_DataSet{false}; // Indicates if the data is set. 252 LineCellIdentifier m_LineCellIdent; 253 }; 254 } 255 256 #ifndef ITK_MANUAL_INSTANTIATION 257 #include "itkGeometricalQuadEdge.hxx" 258 #endif 259 260 #endif 261