/*
* vim: ts=4 sw=4 et tw=0 wm=0
*
* libavoid - Fast, Incremental, Object-avoiding Line Router
*
* Copyright (C) 2004-2009 Monash University
*
* --------------------------------------------------------------------
* Much of the code in this module is based on code published with
* Copyright (C) 1998 Joseph O'Rourke <orourke@cs.smith.edu>
* --------------------------------------------------------------------
* The segmentIntersectPoint function is based on code published and
* described in Franklin Antonio, Faster Line Segment Intersection,
* Graphics Gems III, p. 199-202, code: p. 500-501.
* --------------------------------------------------------------------
*
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* See the file LICENSE.LGPL distributed with the library.
*
* Licensees holding a valid commercial license may use this file in
* accordance with the commercial license agreement provided with the
* library.
*
* This library 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.
*
* Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
*/
#include <cmath>
#include "libavoid/geometry.h"
#include "libavoid/assertions.h"
namespace Avoid {
// Returns true iff the point c lies on the closed segment ab.
// To be used when the points are known to be collinear.
//
// Based on the code of 'Between'.
//
{
// We only call this when we know the points are collinear,
// otherwise we should be checking this here.
if ((fabs(a.x - b.x) > 1) && (a.x != b.x))
{
// not vertical
return (((a.x < c.x) && (c.x < b.x)) ||
((b.x < c.x) && (c.x < a.x)));
}
else
{
return (((a.y < c.y) && (c.y < b.y)) ||
((b.y < c.y) && (c.y < a.y)));
}
}
// Returns true iff the point c lies on the closed segment ab.
//
const double tolerance)
{
}
// Returns true if the segment cd intersects the segment ab, blocking
// visibility.
//
// Based on the code of 'IntersectProp' and 'Intersect'.
//
const Point& d)
{
if (ab_c == 0)
{
return false;
}
if (ab_d == 0)
{
return false;
}
// It's ok for either of the points a or b to be on the line cd,
// so we don't have to check the other two cases.
// Is an intersection if a and b are on opposite sides of cd,
// and c and d are on opposite sides of the line ab.
//
// Note: this is safe even though the textbook warns about it
// since, unlike them, our vecDir is equivilent to 'AreaSign'
// rather than 'Area2'.
}
// Returns true if the segment e1-e2 intersects the shape boundary
// segment s1-s2, blocking visibility.
//
{
{
// Basic intersection of segments.
return true;
}
||
{
// Segments intersect at the endpoint of one of the segments. We
// allow this once, but the second one blocks visibility. Otherwise
// shapes butted up against each other could have visibility through
// shapes.
{
return true;
}
seenIntersectionAtEndpoint = true;
}
return false;
}
// Returns true iff the point p in a valid region that can contain
// shortest paths. a0, a1, a2 are ordered vertices of a shape.
//
// Based on the code of 'InCone'.
//
{
// r is a0--a1
// s is a1--a2
{
// Convex at a1:
//
// !rO rO
// sO sO
//
// ---s---+
// |
// !rO r rO
// !sO | !sO
//
//
if (IgnoreRegions)
{
}
}
else
{
// Concave at a1:
//
// !rO rO
// !sO !sO
//
// +---s---
// |
// !rO r rO
// sO | sO
//
//
}
}
// Gives the side of a corner that a point lies on:
// 1 anticlockwise
// -1 clockwise
// e.g. /|s2
// /s3 -1 / |
// / / |
// 1 |s2 -1 / 1 | -1
// | / |
// |s1 s3/ |s1
//
const Point& p)
{
if (s123 == 1)
{
{
return 1;
}
return -1;
}
else if (s123 == -1)
{
{
return -1;
}
return 1;
}
// c1-c2-c3 are collinear, so just return vecDir from c1-c2
return s12p;
}
// Returns the Euclidean distance between points a and b.
//
{
double xdiff = a.x - b.x;
double ydiff = a.y - b.y;
}
// Returns the Manhattan distance between points a and b.
//
{
}
// Returns the Euclidean distance between points a and b.
//
{
double xdiff = a.x - b.x;
double ydiff = a.y - b.y;
}
// Returns the total length of all line segments in the polygon
{
double l = 0;
{
}
return l;
}
// Uses the dot-product rule to find the angle (radians) between ab and bc
{
double ux = b.x - a.x,
uy = b.y - a.y,
vx = c.x - b.x,
vy = c.y - b.y,
}
// Returns true iff the point q is inside (or on the edge of) the
// polygon argpoly.
//
// This is a fast version that only works for convex shapes. The
// other version (inPolyGen) is more general.
//
{
bool onBorder = false;
for (size_t i = 0; i < n; i++)
{
// point index; i1 = i-1 mod n
if (dir == -1)
{
// Point is outside
return false;
}
// Record if point was on a boundary.
}
if (!countBorder && onBorder)
{
return false;
}
return true;
}
// Returns true iff the point q is inside (or on the edge of) the
// polygon argpoly.
//
// Based on the code of 'InPoly'.
//
{
int Rcross = 0;
int Lcross = 0;
// Copy the argument polygon
// Shift so that q is the origin. This is done for pedogical clarity.
for (size_t i = 0; i < n; ++i)
{
P[i].x = P[i].x - q.x;
P[i].y = P[i].y - q.y;
}
// For each edge e=(i-1,i), see if crosses ray.
for (size_t i = 0; i < n; ++i)
{
// First see if q=(0,0) is a vertex.
if ((P[i].x == 0) && (P[i].y == 0))
{
// We count a vertex as inside.
return true;
}
// point index; i1 = i-1 mod n
// if e "straddles" the x-axis...
// The commented-out statement is logically equivalent to the one
// following.
// if( ((P[i].y > 0) && (P[i1].y <= 0)) ||
// ((P[i1].y > 0) && (P[i].y <= 0)) )
if ((P[i].y > 0) != (P[i1].y > 0))
{
// e straddles ray, so compute intersection with ray.
/ (P[i1].y - P[i].y);
// crosses ray if strictly positive intersection.
if (x > 0)
{
Rcross++;
}
}
// if e straddles the x-axis when reversed...
// if( ((P[i].y < 0) && (P[i1].y >= 0)) ||
// ((P[i1].y < 0) && (P[i].y >= 0)) )
if ((P[i].y < 0) != (P[i1].y < 0))
{
// e straddles ray, so compute intersection with ray.
/ (P[i1].y - P[i].y);
// crosses ray if strictly positive intersection.
if (x < 0)
{
Lcross++;
}
}
}
// q on the edge if left and right cross are not the same parity.
{
// We count the edge as inside.
return true;
}
// Inside iff an odd number of crossings.
{
return true;
}
// Outside.
return false;
}
// Line Segment Intersection
// Original code by Franklin Antonio
//
// The SAME_SIGNS macro assumes arithmetic where the exclusive-or
// operation will work on sign bits. This works for twos-complement,
// and most other machine arithmetic.
#define SAME_SIGNS( a, b ) \
(((long) ((unsigned long) a ^ (unsigned long) b)) >= 0 )
//
{
// X bound box test:
if (Ax < 0)
{
}
else
{
}
if (Bx > 0)
{
}
else
{
}
// Y bound box test:
if (Ay < 0)
{
}
else
{
}
if (By > 0)
{
}
else
{
}
// alpha numerator:
// Both denominator:
// alpha tests:
if (f > 0)
{
if (d < 0 || d > f) return DONT_INTERSECT;
}
else
{
if (d > 0 || d < f) return DONT_INTERSECT;
}
// beta numerator:
// beta tests:
if (f > 0)
{
if (e < 0 || e > f) return DONT_INTERSECT;
}
else
{
if (e > 0 || e < f) return DONT_INTERSECT;
}
// compute intersection coordinates:
if (f == 0) return PARALLEL;
// Numerator:
// Intersection X:
// Intersection Y:
return DO_INTERSECT;
}
// Line Segment Intersection
// Original code by Franklin Antonio
//
{
// alpha numerator:
// Both denominator:
// compute intersection coordinates:
if (f == 0) return PARALLEL;
// Numerator:
// Intersection X:
// Intersection Y:
return DO_INTERSECT;
}
}