summaryrefslogtreecommitdiff
path: root/CSXCAD/src/CSPrimPolygon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CSXCAD/src/CSPrimPolygon.cpp')
-rw-r--r--CSXCAD/src/CSPrimPolygon.cpp294
1 files changed, 294 insertions, 0 deletions
diff --git a/CSXCAD/src/CSPrimPolygon.cpp b/CSXCAD/src/CSPrimPolygon.cpp
new file mode 100644
index 0000000..733fb0a
--- /dev/null
+++ b/CSXCAD/src/CSPrimPolygon.cpp
@@ -0,0 +1,294 @@
+/*
+* Copyright (C) 2008-2012 Thorsten Liebig (Thorsten.Liebig@gmx.de)
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published
+* by the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <sstream>
+#include <iostream>
+#include <limits>
+#include "tinyxml.h"
+#include "stdint.h"
+
+#include "CSPrimPolygon.h"
+#include "CSProperties.h"
+#include "CSUseful.h"
+
+CSPrimPolygon::CSPrimPolygon(unsigned int ID, ParameterSet* paraSet, CSProperties* prop) : CSPrimitives(ID,paraSet,prop)
+{
+ Type=POLYGON;
+ m_NormDir = 0;
+ Elevation.SetParameterSet(paraSet);
+ PrimTypeName = std::string("Polygon");
+}
+
+CSPrimPolygon::CSPrimPolygon(CSPrimPolygon* primPolygon, CSProperties *prop) : CSPrimitives(primPolygon,prop)
+{
+ Type=POLYGON;
+ m_NormDir = primPolygon->m_NormDir;
+ Elevation.Copy(&primPolygon->Elevation);
+ PrimTypeName = std::string("Polygon");
+}
+
+CSPrimPolygon::CSPrimPolygon(ParameterSet* paraSet, CSProperties* prop) : CSPrimitives(paraSet,prop)
+{
+ Type=POLYGON;
+ m_NormDir = 0;
+ Elevation.SetParameterSet(paraSet);
+ PrimTypeName = std::string("Polygon");
+}
+
+CSPrimPolygon::~CSPrimPolygon()
+{
+}
+
+void CSPrimPolygon::SetCoord(int index, double val)
+{
+ if ((index>=0) && (index<(int)vCoords.size())) vCoords.at(index).SetValue(val);
+}
+
+void CSPrimPolygon::SetCoord(int index, const std::string val)
+{
+ if ((index>=0) && (index<(int)vCoords.size())) vCoords.at(index).SetValue(val);
+}
+
+void CSPrimPolygon::AddCoord(double val)
+{
+ vCoords.push_back(ParameterScalar(clParaSet,val));
+}
+
+void CSPrimPolygon::AddCoord(const std::string val)
+{
+ vCoords.push_back(ParameterScalar(clParaSet,val));
+}
+
+void CSPrimPolygon::RemoveCoords(int /*index*/)
+{
+ //not yet implemented
+}
+
+double CSPrimPolygon::GetCoord(int index)
+{
+ if ((index>=0) && (index<(int)vCoords.size())) return vCoords.at(index).GetValue();
+ return 0;
+}
+
+ParameterScalar* CSPrimPolygon::GetCoordPS(int index)
+{
+ if ((index>=0) && (index<(int)vCoords.size())) return &vCoords.at(index);
+ return NULL;
+}
+
+double* CSPrimPolygon::GetAllCoords(size_t &Qty, double* array)
+{
+ Qty=vCoords.size();
+ delete[] array;
+ array = new double[Qty];
+ for (size_t i=0;i<Qty;++i) array[i]=vCoords.at(i).GetValue();
+ return array;
+}
+
+
+bool CSPrimPolygon::GetBoundBox(double dBoundBox[6], bool PreserveOrientation)
+{
+ UNUSED(PreserveOrientation); //has no orientation or preserved anyways
+ bool accurate=false;
+ m_BoundBox_CoordSys = CARTESIAN;
+ if (vCoords.size()<2)
+ {
+ for (int i=0;i<6;++i) dBoundBox[i]=0;
+ return dBoundBox;
+ }
+ double xmin = vCoords.at(0).GetValue(), xmax = vCoords.at(0).GetValue();
+ double ymin = vCoords.at(1).GetValue(), ymax = vCoords.at(1).GetValue();
+ for (size_t i=1;i<vCoords.size()/2;++i)
+ {
+ double x = vCoords.at(2*i).GetValue();
+ double y = vCoords.at(2*i+1).GetValue();
+ if (x<xmin) xmin=x;
+ else if (x>xmax) xmax=x;
+ if (y<ymin) ymin=y;
+ else if (y>ymax) ymax=y;
+ }
+ int nP = (m_NormDir+1)%3;
+ int nPP = (m_NormDir+2)%3;
+ dBoundBox[2*m_NormDir] = dBoundBox[2*m_NormDir+1] = Elevation.GetValue();
+ dBoundBox[2*nP] = xmin;
+ dBoundBox[2*nP+1] = xmax;
+ dBoundBox[2*nPP] = ymin;
+ dBoundBox[2*nPP+1] = ymax;
+ m_Dimension=0;
+ for (int n=0;n<3;++n)
+ {
+ if (dBoundBox[2*n]!=dBoundBox[2*n+1])
+ ++m_Dimension;
+ }
+ return accurate;
+}
+
+bool CSPrimPolygon::IsInside(const double* inCoord, double /*tol*/)
+{
+ if (inCoord==NULL) return false;
+ if (vCoords.size()<2) return false;
+
+ double Coord[3];
+ //transform incoming coordinates into cartesian coords
+ TransformCoordSystem(inCoord,Coord,m_MeshType,CARTESIAN);
+ if (m_Transform && Type==POLYGON)
+ TransformCoords(Coord,true, CARTESIAN);
+
+ for (unsigned int n=0;n<3;++n)
+ if ((m_BoundBox[2*n]>Coord[n]) || (m_BoundBox[2*n+1]<Coord[n])) return false;
+
+ double x=0,y=0;
+ int nP = (m_NormDir+1)%3;
+ int nPP = (m_NormDir+2)%3;
+ x = Coord[nP];
+ y = Coord[nPP];
+
+ int wn = 0;
+
+ size_t np = vCoords.size()/2;
+ double x1 = vCoords[2*np-2].GetValue();
+ double y1 = vCoords[2*np-1].GetValue();
+ double x2 = vCoords[0].GetValue();
+ double y2 = vCoords[1].GetValue();
+ bool startover = y1 >= y ? true : false;
+ bool endover;
+
+ for (size_t i=0;i<np;++i)
+ {
+ x2 = vCoords[2*i].GetValue();
+ y2 = vCoords[2*i+1].GetValue();
+
+ //check if coord is on a cartesian edge exactly
+ if ((x2==x1) && (x1==x) && ( ((y<y1) && (y>y2)) || ((y>y1) && (y<y2)) ))
+ return true;
+ if ((y2==y1) && (y1==y) && ( ((x<x1) && (x>x2)) || ((x>x1) && (x<x2)) ))
+ return true;
+
+ endover = y2 >= y ? true : false;
+ if (startover != endover)
+ {
+ if ((y2 - y)*(x2 - x1) <= (y2 - y1)*(x2 - x))
+ {
+ if (endover) wn ++;
+ }
+ else
+ {
+ if (!endover) wn --;
+ }
+ }
+ startover = endover;
+ y1 = y2;
+ x1 = x2;
+ }
+ // return true if polygon is inside the polygon
+ if (wn != 0)
+ return true;
+
+ return false;
+}
+
+
+bool CSPrimPolygon::Update(std::string *ErrStr)
+{
+ int EC=0;
+ bool bOK=true;
+ if (! ((m_PrimCoordSystem==CARTESIAN) || (m_PrimCoordSystem==UNDEFINED_CS && m_MeshType==CARTESIAN)))
+ {
+ std::cerr << "CSPrimPolygon::Update: Warning: CSPrimPolygon can not be defined in non Cartesian coordinate systems! Result may be unexpected..." << std::endl;
+ ErrStr->append("Warning: CSPrimPolygon can not be defined in non Cartesian coordinate systems! Result may be unexpected...\n");
+ }
+ for (size_t i=1;i<vCoords.size();++i)
+ {
+ EC=vCoords[i].Evaluate();
+ if (EC!=ParameterScalar::NO_ERROR) bOK=false;
+ if ((EC!=ParameterScalar::NO_ERROR) && (ErrStr!=NULL))
+ {
+ bOK=false;
+ std::stringstream stream;
+ stream << std::endl << "Error in Polygon (ID: " << uiID << "): ";
+ ErrStr->append(stream.str());
+ PSErrorCode2Msg(EC,ErrStr);
+ }
+ }
+
+ EC=Elevation.Evaluate();
+ if (EC!=ParameterScalar::NO_ERROR) bOK=false;
+ if ((EC!=ParameterScalar::NO_ERROR) && (ErrStr!=NULL))
+ {
+ bOK=false;
+ std::stringstream stream;
+ stream << std::endl << "Error in Polygon Elevation (ID: " << uiID << "): ";
+ ErrStr->append(stream.str());
+ PSErrorCode2Msg(EC,ErrStr);
+ }
+
+ //update local bounding box used to speedup IsInside()
+ m_BoundBoxValid = GetBoundBox(m_BoundBox);
+
+ return bOK;
+}
+
+bool CSPrimPolygon::Write2XML(TiXmlElement &elem, bool parameterised)
+{
+ CSPrimitives::Write2XML(elem,parameterised);
+
+ WriteTerm(Elevation,elem,"Elevation",parameterised);
+
+ elem.SetAttribute("NormDir",m_NormDir);
+
+ elem.SetAttribute("QtyVertices",(int)vCoords.size()/2);
+
+ for (size_t i=0;i<vCoords.size()/2;++i)
+ {
+ TiXmlElement VT("Vertex");
+ WriteTerm(vCoords.at(i*2),VT,"X1",parameterised);
+ WriteTerm(vCoords.at(i*2+1),VT,"X2",parameterised);
+ elem.InsertEndChild(VT);
+ }
+ return true;
+}
+
+bool CSPrimPolygon::ReadFromXML(TiXmlNode &root)
+{
+ if (CSPrimitives::ReadFromXML(root)==false) return false;
+
+ TiXmlElement *elem = root.ToElement();
+ if (elem==NULL) return false;
+ if (ReadTerm(Elevation,*elem,"Elevation")==false)
+ Elevation.SetValue(0);
+
+ int help;
+ if (elem->QueryIntAttribute("NormDir",&help)!=TIXML_SUCCESS)
+ return false;
+ m_NormDir=help;
+
+ TiXmlElement *VT=root.FirstChildElement("Vertex");
+ if (vCoords.size()!=0) return false;
+ int i=0;
+ while (VT)
+ {
+ for (int n=0;n<2;++n) this->AddCoord(0.0);
+
+ if (ReadTerm(vCoords.at(i*2),*VT,"X1")==false) return false;
+ if (ReadTerm(vCoords.at(i*2+1),*VT,"X2")==false) return false;
+
+ VT=VT->NextSiblingElement("Vertex");
+ ++i;
+ };
+
+ return true;
+}