geometry_util.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2014, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //
00028 // *****************************************************************************
00029 
00030 #include <swri_geometry_util/geometry_util.h>
00031 
00032 namespace swri_geometry_util
00033 {
00034   double DistanceFromPlane(
00035       const tf::Vector3& plane_normal,
00036       const tf::Vector3& plane_point,
00037       const tf::Vector3& point)
00038   {
00039     return plane_normal.normalized().dot(point - plane_point);
00040   }
00041   
00042   tf::Vector3 ProjectPointToPlane(
00043       const tf::Vector3& plane_normal,
00044       const tf::Vector3& plane_point,
00045       const tf::Vector3& point)
00046   {
00047     double d = DistanceFromPlane(plane_normal, plane_point, point);
00048     return point - plane_normal * d;
00049   }
00050 
00051   double DistanceFromLineSegment(
00052       const tf::Vector3& line_start,
00053       const tf::Vector3& line_end,
00054       const tf::Vector3& point)
00055   {    
00056     return point.distance(ProjectToLineSegment(line_start, line_end, point));
00057   }
00058   
00059   double DistanceFromLineSegment(
00060       const cv::Vec2d& line_start,
00061       const cv::Vec2d& line_end,
00062       const cv::Vec2d& point)
00063   {
00064     const cv::Vec2d proj = ProjectToLineSegment(line_start, line_end, point);
00065     return std::sqrt(
00066           (point[0] - proj[0]) * (point[0] - proj[0]) +
00067           (point[1] - proj[1]) * (point[1] - proj[1]));
00068   }
00069 
00070   tf::Vector3 ProjectToLineSegment(
00071       const tf::Vector3& line_start,
00072       const tf::Vector3& line_end,
00073       const tf::Vector3& point)
00074   {
00075     tf::Vector3 v = line_end - line_start;
00076     tf::Vector3 r = point - line_start;
00077     
00078     double t = r.dot(v);
00079     if (t <= 0)
00080     {
00081       return line_start;
00082     }
00083     
00084     double b = v.dot(v);
00085     if (t >= b)
00086     {
00087       return line_end;
00088     }
00089     
00090     return line_start + (t / b) * v;
00091   }
00092 
00093 
00094   cv::Vec2d ProjectToLineSegment(
00095       const cv::Vec2d& line_start,
00096       const cv::Vec2d& line_end,
00097       const cv::Vec2d& point)
00098   {
00099     cv::Point2d v(line_end - line_start);
00100     cv::Point2d r(point - line_start);
00101 
00102     double t = r.dot(v);
00103     if (t <= 0)
00104     {
00105       return line_start;
00106     }
00107 
00108     double b = v.dot(v);
00109     if (t >= b)
00110     {
00111       return line_end;
00112     }
00113 
00114     // Explicitly multiply components since cv::Point doesn't support operation
00115     // in indigo.
00116     return line_start + cv::Vec2d(v.x * (t / b), v.y * (t / b));
00117   }
00118 
00119   bool PointInPolygon(
00120       const std::vector<cv::Vec2d>& polygon,
00121       const cv::Vec2d& point)
00122   {
00123     if (polygon.size() < 2)
00124     {
00125       return false;
00126     }
00127 
00128     bool is_inside = false;
00129     if (((polygon.front()[1] > point[1]) != (polygon.back()[1] > point[1])) &&
00130          (point[0] < (polygon.back()[0] - polygon.front()[0]) * (point[1] - polygon.front()[1]) /
00131                      (polygon.back()[1] - polygon.front()[1]) + polygon.front()[0]))
00132     {
00133       is_inside = !is_inside;
00134     }
00135 
00136     for (size_t i = 1; i < polygon.size(); i++)
00137     {
00138       if (((polygon[i][1] > point[1]) != (polygon[i - 1][1] > point[1])) &&
00139            (point[0] < (polygon[i - 1][0] - polygon[i][0]) * (point[1] - polygon[i][1]) /
00140                        (polygon[i - 1][1] - polygon[i][1]) + polygon[i][0]))
00141       {
00142         is_inside = !is_inside;
00143       }
00144     }
00145 
00146     return is_inside;
00147   }
00148 
00149   double DistanceFromPolygon(
00150       const std::vector<cv::Vec2d>& polygon,
00151       const cv::Vec2d& point)
00152   {
00153     if (polygon.empty())
00154     {
00155       return -1;
00156     }
00157 
00158     double dist = DistanceFromLineSegment(polygon.front(), polygon.back(), point);
00159     for (size_t i = 1; i < polygon.size(); i++)
00160     {
00161       dist = std::min(dist, DistanceFromLineSegment(polygon[i], polygon[i - 1], point));
00162     }
00163 
00164     return dist;
00165   }
00166 
00167   bool ClosestPointToLines(
00168       const tf::Vector3& a1,
00169       const tf::Vector3& a2,
00170       const tf::Vector3& b1,
00171       const tf::Vector3& b2,
00172       tf::Vector3& point)
00173   {
00174     tf::Vector3 u = a1 - a2;
00175     tf::Vector3 v = b1 - b2;
00176     if (u.length() == 0 || v.length() == 0)
00177     {
00178       return false;
00179     }
00180     tf::Vector3 w = u.cross(v);
00181     tf::Vector3 s = b1 - a1;
00182     if (s.length() == 0)
00183     {
00184       point = a1;
00185       return true;
00186     }
00187     double f = w.dot(w);
00188     if (f == 0)
00189     {
00190       return false;
00191     }
00192     tf::Vector3 x = a1 + u * (s.cross(v).dot(w) / f);
00193     tf::Vector3 y = b1 + v * (s.cross(u).dot(w) / f);
00194     point = (x + y) / 2;
00195     return true;
00196   }
00197 }


swri_geometry_util
Author(s): Marc Alban
autogenerated on Thu Jun 6 2019 20:34:40