"Fossies" - the Fresh Open Source Software Archive

Member "reportlab-3.5.23/src/rl_addons/renderPM/libart_lgpl/art_svp_point.c" (14 Mar 2013, 3404 Bytes) of package /linux/privat/reportlab-3.5.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "art_svp_point.c" see the Fossies "Dox" file reference documentation.

    1 /* Libart_LGPL - library of basic graphic primitives
    2  * Copyright (C) 1999 Raph Levien
    3  *
    4  * This library is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU Library General Public
    6  * License as published by the Free Software Foundation; either
    7  * version 2 of the License, or (at your option) any later version.
    8  *
    9  * This library 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 GNU
   12  * Library General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU Library General Public
   15  * License along with this library; if not, write to the
   16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   17  * Boston, MA 02111-1307, USA.
   18  */
   19 
   20 #include "config.h"
   21 #include "art_svp_point.h"
   22 
   23 #include <math.h>
   24 #include "art_misc.h"
   25 
   26 #include "art_svp.h"
   27 
   28 /* Determine whether a point is inside, or near, an svp. */
   29 
   30 /* return winding number of point wrt svp */
   31 /**
   32  * art_svp_point_wind: Determine winding number of a point with respect to svp.
   33  * @svp: The svp.
   34  * @x: The X coordinate of the point.
   35  * @y: The Y coordinate of the point.
   36  *
   37  * Determine the winding number of the point @x, @y with respect to @svp.
   38  *
   39  * Return value: the winding number.
   40  **/
   41 int
   42 art_svp_point_wind (ArtSVP *svp, double x, double y)
   43 {
   44   int i, j;
   45   int wind = 0;
   46 
   47   for (i = 0; i < svp->n_segs; i++)
   48     {
   49       ArtSVPSeg *seg = &svp->segs[i];
   50 
   51       if (seg->bbox.y0 > y)
   52     break;
   53 
   54       if (seg->bbox.y1 > y)
   55     {
   56       if (seg->bbox.x1 < x)
   57         wind += seg->dir ? 1 : -1;
   58       else if (seg->bbox.x0 <= x)
   59         {
   60           double x0, y0, x1, y1, dx, dy;
   61 
   62           for (j = 0; j < seg->n_points - 1; j++)
   63         {
   64           if (seg->points[j + 1].y > y)
   65             break;
   66         }
   67           x0 = seg->points[j].x;
   68           y0 = seg->points[j].y;
   69           x1 = seg->points[j + 1].x;
   70           y1 = seg->points[j + 1].y;
   71 
   72           dx = x1 - x0;
   73           dy = y1 - y0;
   74           if ((x - x0) * dy > (y - y0) * dx)
   75         wind += seg->dir ? 1 : -1;
   76         }
   77     }
   78     }
   79 
   80   return wind;
   81 }
   82 
   83 /**
   84  * art_svp_point_dist: Determine distance between point and svp.
   85  * @svp: The svp.
   86  * @x: The X coordinate of the point.
   87  * @y: The Y coordinate of the point.
   88  *
   89  * Determines the distance of the point @x, @y to the closest edge in
   90  * @svp. A large number is returned if @svp is empty.
   91  *
   92  * Return value: the distance.
   93  **/
   94 double
   95 art_svp_point_dist (ArtSVP *svp, double x, double y)
   96 {
   97   int i, j;
   98   double dist_sq;
   99   double best_sq = -1;
  100 
  101   for (i = 0; i < svp->n_segs; i++)
  102     {
  103       ArtSVPSeg *seg = &svp->segs[i];
  104       for (j = 0; j < seg->n_points - 1; j++)
  105     {
  106       double x0 = seg->points[j].x;
  107       double y0 = seg->points[j].y;
  108       double x1 = seg->points[j + 1].x;
  109       double y1 = seg->points[j + 1].y;
  110 
  111       double dx = x1 - x0;
  112       double dy = y1 - y0;
  113 
  114       double dxx0 = x - x0;
  115       double dyy0 = y - y0;
  116 
  117       double dot = dxx0 * dx + dyy0 * dy;
  118 
  119       if (dot < 0)
  120         dist_sq = dxx0 * dxx0 + dyy0 * dyy0;
  121       else
  122         {
  123           double rr = dx * dx + dy * dy;
  124 
  125           if (dot > rr)
  126         dist_sq = (x - x1) * (x - x1) + (y - y1) * (y - y1);
  127           else
  128         {
  129           double perp = (y - y0) * dx - (x - x0) * dy;
  130 
  131           dist_sq = perp * perp / rr;
  132         }
  133         }
  134       if (best_sq < 0 || dist_sq < best_sq)
  135         best_sq = dist_sq;
  136     }
  137     }
  138 
  139   if (best_sq >= 0)
  140     return sqrt (best_sq);
  141   else
  142     return 1e12;
  143 }
  144