EMODnet Quantized Mesh Generator for Cesium
generate_border_features_polylines.h
1 // Copyright (c) 2018 Coronis Computing S.L. (Spain)
2 // All rights reserved.
3 //
4 // This file is part of EMODnet Quantized Mesh Generator for Cesium.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 //
19 // Author: Ricard Campos (ricardcd@gmail.com)
20 
21 #ifndef EMODNET_QMGC_GENERATE_BORDER_FEATURES_POLYLINES_H
22 #define EMODNET_QMGC_GENERATE_BORDER_FEATURES_POLYLINES_H
23 
24 #include "tin_creation/tin_creation_cgal_types.h"
25 #include "cgal_utils.h"
26 #include <CGAL/centroid.h>
27 
39 template <class Polyhedron>
40 std::vector<std::vector<typename Polyhedron::Point_3>>
41 generateBorderFeaturesPolylines( const Polyhedron& surface,
42  const bool& constrainEastBorder = true,
43  const bool& constrainWestBorder = true,
44  const bool& constrainNorthBorder = true,
45  const bool& constrainSouthBorder = true )
46 {
47  typedef typename Polyhedron::Point_3 Point_3;
48  typedef typename Polyhedron::Traits::FT FT;
49  typedef typename Polyhedron::Vertex_const_iterator Vertex_const_iterator;
50  typedef std::vector<Point_3> Polyline;
51  typedef std::vector<Polyline> Polylines;
52 
53  Polylines polylines ;
54 
55  // Compute the middle point for reference
56  std::vector<Point_3 > pts ;
57  for ( Vertex_const_iterator it = surface.vertices_begin(); it != surface.vertices_end(); ++it )
58  pts.push_back(it->point());
59  Point_3 c3 = CGAL::centroid(pts.begin(), pts.end(),CGAL::Dimension_tag<0>());
60  FT midX = c3.x() ;
61  FT midY = c3.y() ;
62 
63  // NOTE: The naming of the functions is a bit misleading in CGAL's documentation...
64  // The docs always refer to border halfedges as those halfedges incident to the "hole". However, the range [border_halfedges_begin(), halfedges_end()) includes ALL halfedges in the border, those who are incident to the hole AND ALSO their opposites, incident on a face.
65  // For this reason, we check if this is a real "border halfedge", and take the opposite if it is not
66  typename Polyhedron::Halfedge_const_handle startHE = surface.border_halfedges_begin() ;
67  if (!startHE->is_border())
68  startHE = startHE->opposite() ;
69  typename Polyhedron::Halfedge_const_handle e = startHE ;
70 
71  Polyline plU; // Polyline for unconstrained border edges. This should be entered as a sequential polyline, not individual edges!
72  bool prevIsRegularBorder = false ; // Checks wether the previously visited edge is a "regular" border edge, or it is a "constrained" border edge. When this is false, we should start a new polyline
73  do {
74  // Relevant geometric info of the current edge
75  Point_3 p0 = e->vertex()->point() ; // This is the point we will take care of now
76  Point_3 p1 = e->prev()->vertex()->point() ; // This is the previous vertex, with which p0 forms an edge
77 
78  double diffX = fabs( p1.x() - p0.x() ) ;
79  double diffY = fabs( p1.y() - p0.y() ) ;
80 
81  if ( ( constrainEastBorder && diffX < diffY && p0.x() > midX ) ||
82  ( constrainWestBorder && diffX < diffY && p0.x() < midX ) ||
83  ( constrainNorthBorder && diffY < diffX && p0.y() > midY ) ||
84  ( constrainSouthBorder && diffY < diffX && p0.y() < midY ) ) {
85  // We add this edge as a polyline, since polylines' endpoints are preserved by the meshing algorithm
86  Polyline pl;
87  pl.push_back(p0);
88  pl.push_back(p1);
89 
90  polylines.push_back(pl);
91  prevIsRegularBorder = false;
92  }
93  else {
94  // The edge is a border edge, so we must constrain it to remain in the mesh, but we don't fix its vertices
95  if (!prevIsRegularBorder) {
96  if (!plU.empty())
97  polylines.push_back(plU);
98  plU.clear() ;
99  plU.push_back(p1) ;
100  plU.push_back(p0) ;
101  prevIsRegularBorder = true ;
102  }
103  else {
104  plU.push_back(p0);
105  }
106  }
107 
108  if (prevIsRegularBorder)
109  // If the edge is regular so far, check if it is incident to a corner (they need to be endpoints of the polylines to be maintained during meshing)
110  prevIsRegularBorder = !isTileCorner<Polyhedron>(e) ;
111 
112  e = e->next() ; // Advancing in this way should circulate through the "hole", if we start in a border halfedge
113  }
114  while ( e != startHE ); // Finish when we reach the starting point
115 
116  if (!plU.empty())
117  polylines.push_back(plU) ;
118 
119  return polylines ;
120 }
121 
122 #endif //EMODNET_QMGC_GENERATE_BORDER_FEATURES_POLYLINES_H
Set of miscellaneous functions extending the functionality of the CGAL library.