Flow123d  release_2.2.0-914-gf1a3a4f
polygon.cpp
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file polygon.cpp
15  * @brief
16  */
17 
18 #include <iostream>
19 #include <vector>
20 
24 
25 using namespace mathfce;
26 
27 namespace ngh {
28 
29 
30 int TPolygon::numberInstance = 0;
31 
32 int TPolygon::generateId() {
33  return TPolygon::numberInstance++;
34 }
35 
36 TPolygon::TPolygon() {
37  id = generateId();
38 
39  area_is_actual = false;
40  center_is_actual = false;
41  center.SetCoord(0, 0, 0);
42  area = 0;
43 }
44 
45 TPolygon::~TPolygon() {
46  TPolygon *pol = this;
48 
49  FOR_POL_VERTECES(pol, iv) {
50  delete (*iv);
51  }
52  verteces.clear();
53 }
54 
55 std::ostream & operator <<(std::ostream& stream, const TPolygon& p) {
57  int i = 0;
58 
59  // in the following, the explicit typecast is neccessary, since otherwise
60  // the operators '=' and '!=' are not defined (I wander why constantness
61  // of the Polygon instance can lead to this
62 
63  FOR_POL_VERTECES((TPolygon*) & p, iv) {
64  stream << "V" << i << " = " << (*iv)->GetPoint() << "\n";
65  i++;
66  }
67  return stream;
68 }
69 
70 void TPolygon::Add(const TPoint& P) {
72 
73  FOR_POL_VERTECES(this, iv) {
74  if ((*iv)->GetPoint() == P)
75  return;
76  }
77  TVertex* V = new TVertex(P);
78  int insertPos = InsertPosition(*V);
79  area_is_actual = false;
80  center_is_actual = false;
81  verteces.insert(verteces.begin() + insertPos, V);
82  return;
83 }
84 
85 double TPolygon::GetArea() {
86  if (!center_is_actual)
87  ComputeCenter();
88  if (area_is_actual)
89  return area;
90  ComputeArea();
91  return area;
92 }
93 
94 void TPolygon::ComputeCenter() {
95  int i;
96  double D[ 3 ] = {0, 0, 0};
98  if (verteces.size() < 3) {
99  center.SetCoord(D[ 0 ], D[ 1 ], D[ 2 ]);
100  return;
101  }
102 
103  FOR_POL_VERTECES(this, iv) {
104  for (i = 0; i < 3; i++)
105  D[ i ] += (*iv)->GetPoint().Get(i + 1);
106  }
107  for (i = 0; i < 3; i++)
108  D[ i ] /= verteces.size();
109  center.SetCoord(D[ 0 ], D[ 1 ], D[ 2 ]);
110  center_is_actual = true;
111  return;
112 }
113 
114 TPoint TPolygon::GetCenter() {
115  if (center_is_actual)
116  return center;
117  ComputeCenter();
118  return center;
119 }
120 
121 int TPolygon::InsertPosition(const TVertex& Vx) {
122  TVertex *V1, *V2;
123  TVector U1, U2, N;
124  int pos = 0;
125 
126  // if size < 2 new vertex is insert at the end
127  if (verteces.size() < 2)
128  return verteces.size();
129 
130  // if size == 2 new vertex is insert at the end and normal vector is computed
131  if (verteces.size() == 2) {
132  V1 = (*(verteces.begin()));
133  V2 = (*(verteces.begin() + 1));
134 
135  U1 = V2->GetPoint() - V1->GetPoint();
136  U2 = Vx.GetPoint() - V1->GetPoint();
137  normal_vector = Cross(U1, U2);
138  return verteces.size();
139  }
140 
141  for (unsigned int i=0; i<verteces.size(); ++i) {
142  V1 = (*(verteces.begin() + i));
143  if (i == verteces.size() - 1)
144  V2 = (*(verteces.begin()));
145  else
146  V2 = (*(verteces.begin() + i + 1));
147  U1 = V2->GetPoint() - V1->GetPoint();
148  U2 = Vx.GetPoint() - V1->GetPoint();
149  N = Cross(U1, U2);
150  if (Dot(N, normal_vector) < 0) {
151  if (pos > 0) MessageOut() << "TPolygon::InsertPosition - ERROR: only one vector product must be negative\n";
152  pos = i+1;
153  }
154  }
155 
156  if (pos == 0) MessageOut() << "TPolygon::InsertPosition - ERROR: no vector product is negative\n";
157  return pos;
158 }
159 
160 void TPolygon::ComputeArea() {
162 
163  TTriangle T;
164  TPoint P1, P2, P3;
165 
166  area = 0;
167  area_is_actual = true;
168  if (verteces.size() < 3)
169  return;
170 
171  FOR_POL_VERTECES(this, iv) {
172  P1 = center;
173  P2 = (*iv)->GetPoint();
174  if (iv == verteces.end() - 1)
175  P3 = (*verteces.begin())->GetPoint();
176  else
177  P3 = (*(iv + 1))->GetPoint();
178  T.SetPoints(P1, P2, P3);
179  area += T.GetArea();
180  }
181  return;
182 }
183 
184 } // namespace ngh
double GetArea()
Definition: triangle.cpp:148
#define MessageOut()
Macro defining &#39;message&#39; record of log.
Definition: logger.hh:243
Definition: abscissa.h:25
double Dot(const TVector &, const TVector &)
Definition: vector.cpp:199
#define FOR_POL_VERTECES(i, j)
Definition: polygon.h:27
void SetPoints(const TPoint &, const TPoint &, const TPoint &)
Definition: triangle.cpp:129
TPoint GetPoint() const
Definition: vertex.cpp:39
TVector Cross(const TVector &, const TVector &)
Definition: vector.cpp:182
std::ostream & operator<<(std::ostream &stream, const TPolygon &p)
Definition: polygon.cpp:55