Polygon3D.cpp
Go to the documentation of this file.
00001 //
00002 //
00003 // Polygon3d.cpp
00004 //
00005 
00006 #include <cmath>
00007 
00008 #include "Polygon3D.hpp"
00009 #include "Polygon2D.hpp"
00010 #include <algorithm> // for std::sort()
00011 #include <iterator>
00012 #include <sstream>
00013 
00014 
00015 // ////////////////////////////////////////////////////////////
00016 namespace datatypes
00017 {
00018 
00019 Polygon3D::Polygon3D()
00020 {
00021 }
00022 
00023 Polygon3D::Polygon3D(const Point3D& p1)
00024 {
00025         push_back(p1);          // Insert the element at the end of the list
00026 }
00027 
00028 Polygon3D::Polygon3D(const Point3D& p1, const Point3D& p2)
00029 {
00030         push_back(p1);          // Insert the element at the end of the list
00031         push_back(p2);          // Insert the element at the end of the list
00032 }
00033 Polygon3D::Polygon3D(const Point3D& p1, const Point3D& p2, const Point3D& p3)
00034 {
00035         push_back(p1);          // Insert the element at the end of the list
00036         push_back(p2);          // Insert the element at the end of the list
00037         push_back(p3);          // Insert the element at the end of the list
00038 }
00039 
00040 //
00041 // Initialize this polygon with an existing one
00042 //
00043 Polygon3D::Polygon3D(const base_class& other_vector)
00044         : base_class(other_vector)
00045 {
00046 }
00047 
00048 /*
00049 void Polygon3D::fromString(const std::string& polyString)
00050 {
00051         clear();
00052 
00053         typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00054         tokenizer listOfTokens(polyString, boost::char_separator<char>(Polygon2D::getSeparatorCharacters()));
00055         for (tokenizer::const_iterator iter = listOfTokens.begin();
00056                  iter != listOfTokens.end(); ++iter)
00057         {
00058                 float x = boost::lexical_cast<float>(*iter);
00059                 ++iter;
00060                 if (iter == listOfTokens.end())
00061                         throw std::runtime_error("When parsing a Polygon3D string, the last point only has a x component.");
00062                 float y = boost::lexical_cast<float>(*iter);
00063                 ++iter;
00064                 if (iter == listOfTokens.end())
00065                         throw std::runtime_error("When parsing a Polygon3D string, the last point only has a x and y component.");
00066                 float z = boost::lexical_cast<float>(*iter);
00067                 this->push_back(Point3D(x, y, z));
00068         }
00069 }
00070 */
00071 
00072 
00074 std::string Polygon3D::toString() const
00075 {
00076         std::ostringstream o;
00077         o << *this;
00078         return o.str();
00079 }
00080 
00082 static bool comparePointAngleXYPlane(const Point3D& p1, const Point3D& p2)
00083 {
00084         return (p1.getAngleAroundZ() < p2.getAngleAroundZ());
00085 }
00086 
00091 void Polygon3D::sortForAngleXYPlane()
00092 {
00093         std::sort(begin(), end(), comparePointAngleXYPlane);
00094 }
00095 
00096 
00097 
00099 std::ostream& operator<<(std::ostream& os, const Polygon3D& poly)
00100 {
00101         os << "[ ";
00102         if (!poly.empty())
00103         {
00104                 // Polygon contains at least one element
00105                 std::copy (poly.begin(), poly.end() - 1,
00106                                    std::ostream_iterator<Point3D>(os, ", "));
00107                 os << poly.back();      // Last element of the polygon
00108         }
00109         os << " ]";
00110         return os;
00111 }
00112 
00113 // Important: this code exists in a very similar for in the Polygon2D class.
00114 // Bugfixes should be applied there also.
00115 Polygon3D Polygon3D::getMovedPath(double dist) const
00116 {
00117         Polygon3D moved;
00118 
00119         // We need 2 points minimum to have a valid path
00120         if (size() < 2)
00121         {
00122                 if (size() > 0)
00123                 {
00124                         // only 1 point, move only y-direction.
00125                         moved.push_back(at(0) + Point3D(0.0, dist, 0.0));
00126                 }
00127                 return moved; // finished.
00128         }
00129 
00130         // Here we have at least 2 points.
00131 
00132         // We need 2 segments to calculate the shift direction.
00133         // Start with 90 deg angle.
00134         double lastAng, ang; // Angles of the path segments.
00135         Point3D lastPos = at(0);
00136 
00137         // The first segment is also handles in the loop. The needed but not existing preceeding segment
00138         // is assumed to have the same direction.
00139         lastAng = (at(1) - lastPos).getAngleAroundZ();
00140         double edgeDist; // path width in a corner, is >= dist (path width)
00141         Point3D shiftVec; // Vector from source edge to new edge.
00142         Point3D pt;
00143         size_t i;
00144         for (i = 1; i < size(); i++)
00145         {
00146                 pt = at(i);
00147                 ang = (pt - lastPos).getAngleAroundZ();
00148                 double diffAng = normalizeRadians(lastAng - ang);
00149                 double halfAngBetween = diffAng / 2.0;
00150 
00151                 // Calculation of the length from edge to new edge
00152                 // The direction to the new path point (new edge)  has the direction of the half angle between both segments.
00153                 double cosHalfAngBetween = std::abs(cos(halfAngBetween));
00154 
00155                 // Do not calculate moved point if path angle to small
00156                 // This usually happens, if we have a zick-zack situation.
00157                 if ((cosHalfAngBetween) > 0.195)  //  0.195 = cos( 1/2 * PI  +- 1/16 * PI)
00158                 {
00159                         edgeDist = dist / cosHalfAngBetween;
00160                         shiftVec = Point3D(0.0, edgeDist, 0.0);
00161                         shiftVec.rotateAroundZ(lastAng - halfAngBetween);
00162                         Point3D np = lastPos + shiftVec;
00163 
00164                         moved.push_back(np);
00165                 }
00166 
00167                 lastAng = ang;
00168                 lastPos = pt;
00169         }
00170         // Add last point
00171         moved.push_back(lastPos + shiftVec);
00172 
00173         return moved;
00174 }
00175 
00176 }       // namespace datatypes
00177 


libsick_ldmrs
Author(s): SICK AG , Martin Günther , Jochen Sprickerhof
autogenerated on Wed Jun 14 2017 04:04:50