1 /*
2 * Copyright (C) 2008-2012 Thorsten Liebig (Thorsten.Liebig@gmx.de)
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <sstream>
19 #include <iostream>
20 #include <limits>
21 #include "tinyxml.h"
22 #include "stdint.h"
23
24 #include "CSPrimPolygon.h"
25 #include "CSProperties.h"
26 #include "CSUseful.h"
27
CSPrimPolygon(unsigned int ID,ParameterSet * paraSet,CSProperties * prop)28 CSPrimPolygon::CSPrimPolygon(unsigned int ID, ParameterSet* paraSet, CSProperties* prop) : CSPrimitives(ID,paraSet,prop)
29 {
30 Type=POLYGON;
31 m_NormDir = 0;
32 Elevation.SetParameterSet(paraSet);
33 PrimTypeName = std::string("Polygon");
34 }
35
CSPrimPolygon(CSPrimPolygon * primPolygon,CSProperties * prop)36 CSPrimPolygon::CSPrimPolygon(CSPrimPolygon* primPolygon, CSProperties *prop) : CSPrimitives(primPolygon,prop)
37 {
38 Type=POLYGON;
39 m_NormDir = primPolygon->m_NormDir;
40 Elevation.Copy(&primPolygon->Elevation);
41 PrimTypeName = std::string("Polygon");
42 }
43
CSPrimPolygon(ParameterSet * paraSet,CSProperties * prop)44 CSPrimPolygon::CSPrimPolygon(ParameterSet* paraSet, CSProperties* prop) : CSPrimitives(paraSet,prop)
45 {
46 Type=POLYGON;
47 m_NormDir = 0;
48 Elevation.SetParameterSet(paraSet);
49 PrimTypeName = std::string("Polygon");
50 }
51
~CSPrimPolygon()52 CSPrimPolygon::~CSPrimPolygon()
53 {
54 }
55
GetCopy(CSProperties * prop)56 CSPrimPolygon* CSPrimPolygon::GetCopy(CSProperties *prop) {return new CSPrimPolygon(this,prop);}
57
SetCoord(int index,double val)58 void CSPrimPolygon::SetCoord(int index, double val)
59 {
60 if ((index>=0) && (index<(int)vCoords.size())) vCoords.at(index).SetValue(val);
61 }
62
SetCoord(int index,const std::string val)63 void CSPrimPolygon::SetCoord(int index, const std::string val)
64 {
65 if ((index>=0) && (index<(int)vCoords.size())) vCoords.at(index).SetValue(val);
66 }
67
AddCoord(double val)68 void CSPrimPolygon::AddCoord(double val)
69 {
70 vCoords.push_back(ParameterScalar(clParaSet,val));
71 }
72
AddCoord(const std::string val)73 void CSPrimPolygon::AddCoord(const std::string val)
74 {
75 vCoords.push_back(ParameterScalar(clParaSet,val));
76 }
77
RemoveCoords(int)78 void CSPrimPolygon::RemoveCoords(int /*index*/)
79 {
80 //not yet implemented
81 }
82
GetCoord(int index)83 double CSPrimPolygon::GetCoord(int index)
84 {
85 if ((index>=0) && (index<(int)vCoords.size())) return vCoords.at(index).GetValue();
86 return 0;
87 }
88
GetCoordPS(int index)89 ParameterScalar* CSPrimPolygon::GetCoordPS(int index)
90 {
91 if ((index>=0) && (index<(int)vCoords.size())) return &vCoords.at(index);
92 return NULL;
93 }
94
GetQtyCoords()95 size_t CSPrimPolygon::GetQtyCoords() {return vCoords.size()/2;}
96
GetAllCoords(size_t & Qty,double * array)97 double* CSPrimPolygon::GetAllCoords(size_t &Qty, double* array)
98 {
99 Qty=vCoords.size();
100 delete[] array;
101 array = new double[Qty];
102 for (size_t i=0;i<Qty;++i) array[i]=vCoords.at(i).GetValue();
103 return array;
104 }
105
SetNormDir(int dir)106 void CSPrimPolygon::SetNormDir(int dir) {if ((dir>=0) && (dir<3)) m_NormDir=dir;}
107
GetBoundBox(double dBoundBox[6],bool PreserveOrientation)108 bool CSPrimPolygon::GetBoundBox(double dBoundBox[6], bool PreserveOrientation)
109 {
110 UNUSED(PreserveOrientation); //has no orientation or preserved anyways
111 bool accurate=false;
112 m_BoundBox_CoordSys = CARTESIAN;
113 if (vCoords.size()<2)
114 {
115 for (int i=0;i<6;++i) dBoundBox[i]=0;
116 return dBoundBox;
117 }
118 double xmin = vCoords.at(0).GetValue(), xmax = vCoords.at(0).GetValue();
119 double ymin = vCoords.at(1).GetValue(), ymax = vCoords.at(1).GetValue();
120 for (size_t i=1;i<vCoords.size()/2;++i)
121 {
122 double x = vCoords.at(2*i).GetValue();
123 double y = vCoords.at(2*i+1).GetValue();
124 if (x<xmin) xmin=x;
125 else if (x>xmax) xmax=x;
126 if (y<ymin) ymin=y;
127 else if (y>ymax) ymax=y;
128 }
129 int nP = (m_NormDir+1)%3;
130 int nPP = (m_NormDir+2)%3;
131 dBoundBox[2*m_NormDir] = dBoundBox[2*m_NormDir+1] = Elevation.GetValue();
132 dBoundBox[2*nP] = xmin;
133 dBoundBox[2*nP+1] = xmax;
134 dBoundBox[2*nPP] = ymin;
135 dBoundBox[2*nPP+1] = ymax;
136 m_Dimension=0;
137 for (int n=0;n<3;++n)
138 {
139 if (dBoundBox[2*n]!=dBoundBox[2*n+1])
140 ++m_Dimension;
141 }
142 return accurate;
143 }
144
IsInside(const double * inCoord,double)145 bool CSPrimPolygon::IsInside(const double* inCoord, double /*tol*/)
146 {
147 if (inCoord==NULL) return false;
148 if (vCoords.size()<2) return false;
149
150 double Coord[3];
151 //transform incoming coordinates into cartesian coords
152 TransformCoordSystem(inCoord,Coord,m_MeshType,CARTESIAN);
153 if (m_Transform && Type==POLYGON)
154 TransformCoords(Coord,true, CARTESIAN);
155
156 for (unsigned int n=0;n<3;++n)
157 if ((m_BoundBox[2*n]>Coord[n]) || (m_BoundBox[2*n+1]<Coord[n])) return false;
158
159 double x=0,y=0;
160 int nP = (m_NormDir+1)%3;
161 int nPP = (m_NormDir+2)%3;
162 x = Coord[nP];
163 y = Coord[nPP];
164
165 int wn = 0;
166
167 size_t np = vCoords.size()/2;
168 double x1 = vCoords[2*np-2].GetValue();
169 double y1 = vCoords[2*np-1].GetValue();
170 double x2 = vCoords[0].GetValue();
171 double y2 = vCoords[1].GetValue();
172 bool startover = y1 >= y ? true : false;
173 bool endover;
174
175 for (size_t i=0;i<np;++i)
176 {
177 x2 = vCoords[2*i].GetValue();
178 y2 = vCoords[2*i+1].GetValue();
179
180 //check if coord is on a cartesian edge exactly
181 if ((x2==x1) && (x1==x) && ( ((y<y1) && (y>y2)) || ((y>y1) && (y<y2)) ))
182 return true;
183 if ((y2==y1) && (y1==y) && ( ((x<x1) && (x>x2)) || ((x>x1) && (x<x2)) ))
184 return true;
185
186 endover = y2 >= y ? true : false;
187 if (startover != endover)
188 {
189 if ((y2 - y)*(x2 - x1) <= (y2 - y1)*(x2 - x))
190 {
191 if (endover) wn ++;
192 }
193 else
194 {
195 if (!endover) wn --;
196 }
197 }
198 startover = endover;
199 y1 = y2;
200 x1 = x2;
201 }
202 // return true if polygon is inside the polygon
203 if (wn != 0)
204 return true;
205
206 return false;
207 }
208
209
Update(std::string * ErrStr)210 bool CSPrimPolygon::Update(std::string *ErrStr)
211 {
212 int EC=0;
213 bool bOK=true;
214 if (! ((m_PrimCoordSystem==CARTESIAN) || (m_PrimCoordSystem==UNDEFINED_CS && m_MeshType==CARTESIAN)))
215 {
216 std::cerr << "CSPrimPolygon::Update: Warning: CSPrimPolygon can not be defined in non Cartesian coordinate systems! Result may be unexpected..." << std::endl;
217 ErrStr->append("Warning: CSPrimPolygon can not be defined in non Cartesian coordinate systems! Result may be unexpected...\n");
218 }
219 for (size_t i=1;i<vCoords.size();++i)
220 {
221 EC=vCoords[i].Evaluate();
222 if (EC!=ParameterScalar::PS_NO_ERROR) bOK=false;
223 if ((EC!=ParameterScalar::PS_NO_ERROR) && (ErrStr!=NULL))
224 {
225 bOK=false;
226 std::stringstream stream;
227 stream << std::endl << "Error in Polygon (ID: " << uiID << "): ";
228 ErrStr->append(stream.str());
229 PSErrorCode2Msg(EC,ErrStr);
230 }
231 }
232
233 EC=Elevation.Evaluate();
234 if (EC!=ParameterScalar::PS_NO_ERROR) bOK=false;
235 if ((EC!=ParameterScalar::PS_NO_ERROR) && (ErrStr!=NULL))
236 {
237 bOK=false;
238 std::stringstream stream;
239 stream << std::endl << "Error in Polygon Elevation (ID: " << uiID << "): ";
240 ErrStr->append(stream.str());
241 PSErrorCode2Msg(EC,ErrStr);
242 }
243
244 //update local bounding box used to speedup IsInside()
245 m_BoundBoxValid = GetBoundBox(m_BoundBox);
246
247 return bOK;
248 }
249
Write2XML(TiXmlElement & elem,bool parameterised)250 bool CSPrimPolygon::Write2XML(TiXmlElement &elem, bool parameterised)
251 {
252 CSPrimitives::Write2XML(elem,parameterised);
253
254 WriteTerm(Elevation,elem,"Elevation",parameterised);
255
256 elem.SetAttribute("NormDir",m_NormDir);
257
258 elem.SetAttribute("QtyVertices",(int)vCoords.size()/2);
259
260 for (size_t i=0;i<vCoords.size()/2;++i)
261 {
262 TiXmlElement VT("Vertex");
263 WriteTerm(vCoords.at(i*2),VT,"X1",parameterised);
264 WriteTerm(vCoords.at(i*2+1),VT,"X2",parameterised);
265 elem.InsertEndChild(VT);
266 }
267 return true;
268 }
269
ReadFromXML(TiXmlNode & root)270 bool CSPrimPolygon::ReadFromXML(TiXmlNode &root)
271 {
272 if (CSPrimitives::ReadFromXML(root)==false) return false;
273
274 TiXmlElement *elem = root.ToElement();
275 if (elem==NULL) return false;
276 if (ReadTerm(Elevation,*elem,"Elevation")==false)
277 Elevation.SetValue(0);
278
279 int help;
280 if (elem->QueryIntAttribute("NormDir",&help)!=TIXML_SUCCESS)
281 return false;
282 m_NormDir=help;
283
284 TiXmlElement *VT=root.FirstChildElement("Vertex");
285 if (vCoords.size()!=0) return false;
286 int i=0;
287 while (VT)
288 {
289 for (int n=0;n<2;++n) this->AddCoord(0.0);
290
291 if (ReadTerm(vCoords.at(i*2),*VT,"X1")==false) return false;
292 if (ReadTerm(vCoords.at(i*2+1),*VT,"X2")==false) return false;
293
294 VT=VT->NextSiblingElement("Vertex");
295 ++i;
296 };
297
298 return true;
299 }
300