EMODnet Quantized Mesh Generator for Cesium
extract_tile_borders_from_polyhedron.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_CGAL_EXTRACT_TILE_BORDERS_FROM_POLYHEDRON_H
22 #define EMODNET_QMGC_CGAL_EXTRACT_TILE_BORDERS_FROM_POLYHEDRON_H
23 
24 #include "tin_creation/tin_creation_cgal_types.h"
25 #include <CGAL/centroid.h>
26 
27 
28 
34 template<class Polyhedron>
35 bool extractTileBordersFromPolyhedron(const Polyhedron& poly,
36  std::vector<typename Polyhedron::Point_3>& easternBorderPts,
37  std::vector<typename Polyhedron::Point_3>& westernBorderPts,
38  std::vector<typename Polyhedron::Point_3>& northernBorderPts,
39  std::vector<typename Polyhedron::Point_3>& southernBorderPts,
40  typename Polyhedron::Point_3& cornerPoint00,
41  typename Polyhedron::Point_3& cornerPoint01,
42  typename Polyhedron::Point_3& cornerPoint10,
43  typename Polyhedron::Point_3& cornerPoint11)
44 {
45  typedef typename Polyhedron::Point_3 Point_3;
46  typedef typename Polyhedron::Traits::FT FT;
47  typedef typename Polyhedron::Vertex_const_iterator Vertex_const_iterator;
48  typedef typename Polyhedron::Halfedge_const_iterator Halfedge_const_iterator;
49 
50  easternBorderPts.clear();
51  westernBorderPts.clear();
52  northernBorderPts.clear();
53  southernBorderPts.clear();
54 
55  int numCorners = 0 ;
56 
57  std::vector<Point_3 > pts ;
58  for ( Vertex_const_iterator it = poly.vertices_begin(); it != poly.vertices_end(); ++it )
59  pts.push_back(it->point());
60  Point_3 c3 = CGAL::centroid(pts.begin(), pts.end(),CGAL::Dimension_tag<0>());
61  FT midX = c3.x() ;
62  FT midY = c3.y() ;
63 
64  Halfedge_const_iterator e = poly.border_halfedges_begin() ;
65  ++e ; // We start at the second halfedge!
66  while( e->is_border() )
67  {
68  // Relevant geometric info of the current edge
69  Point_3 p0 = e->vertex()->point() ; // This is the point we will take care of now
70  Point_3 p1 = e->prev()->vertex()->point() ; // This is the previous vertex, with which p0 forms an edge
71 
72  // Differences between the points in the edge
73  double diffX = fabs( p1.x() - p0.x() ) ;
74  double diffY = fabs( p1.y() - p0.y() ) ;
75 
76  // Check if it is a corner point: the next vertex changes from vertical to horizontal or viceversa
77  // If it is a corner point, we should add it twice to the corresponding border
78 
79  // Next edge on the border (since we are in a border halfedge, the next operator points to the next halfedge around the "hole"
80  Point_3 p2 = e->next()->vertex()->point() ;
81 
82  double diffXNext = fabs( p2.x() - p0.x() ) ;
83  double diffYNext = fabs( p2.y() - p0.y() ) ;
84  bool isCorner = ( ( diffX < diffY ) && ( diffXNext > diffYNext ) ) ||
85  ( ( diffX > diffY ) && ( diffXNext < diffYNext ) ) ;
86 
87  if ( isCorner ) {
88  numCorners++ ;
89  if ( p0.x() < midX && p0.y() < midY ) { // Corner (0, 0)
90  cornerPoint00 = p0;
91  westernBorderPts.push_back(p0);
92  southernBorderPts.push_back(p0);
93  }
94  else if ( p0.x() < midX && p0.y() > midY ) { // Corner (0, 1)
95  cornerPoint01 = p0;
96  westernBorderPts.push_back(p0);
97  northernBorderPts.push_back(p0);
98  }
99  else if ( p0.x() > midX && p0.y() > midY ) { // Corner (1, 1)
100  cornerPoint11 = p0;
101  easternBorderPts.push_back(p0);
102  northernBorderPts.push_back(p0);
103  }
104  else { // p0.x() > 0.5 && p0.y() < 0.5 ) // Corner (1, 0)
105  cornerPoint10 = p0;
106  easternBorderPts.push_back(p0);
107  southernBorderPts.push_back(p0);
108  }
109  }
110  else {
111  if (diffX < diffY) {
112  // Vertical edge, can be a western or eastern edge
113  if (p0.x() < midX) {
114  // Western border edge/vertex
115  westernBorderPts.push_back(p0);
116  } else { // p0.x() >= 0.5
117  // Eastern border vertex
118  easternBorderPts.push_back(p0);
119  }
120  } else { // diffX >= diffY
121  // Horizontal edge, can be a northern or southern edge
122  if (p0.y() < midY) {
123  // Southern border edge/vertex
124  southernBorderPts.push_back(p0);
125  } else { // p0.y() >= 0.5
126  // Northern border edge/vertex
127  northernBorderPts.push_back(p0);
128  }
129  }
130  }
131 
132  // Advance 2 positions (i.e., skip non-border halfedges)
133  std::advance(e,2) ;
134  }
135 
136  return numCorners == 4 ;
137 }
138 
139 #endif //EMODNET_QMGC_CGAL_EXTRACT_TILE_BORDERS_FROM_POLYHEDRON_H