Contest Algorithms January 2016 Overview of the CG library code. Look at dot product, cross product,...

Post on 18-Jan-2016

229 views 0 download

Transcript of Contest Algorithms January 2016 Overview of the CG library code. Look at dot product, cross product,...

1

Contest AlgorithmsJanuary 2016

Overview of the CG library code.Look at dot product, cross product, ccw(), intersection, closest point, basic polygon

methods.

14. Computational Geometry Basics

Contest Algorithms: 14. CG Basics

Points (x, y) Cartesian coordinates (r, Θ) Polar coordinates

Lines 2-tuple (m, c) using y = mx + c 3-tuple (a, b, c) using ax + by = c Two points P0, P1 on the line using P(t) = (1-t)P0 + t P1

Line Segments Positioned using their end points

Polygons Ordered list of points that form a closed shape

1. Simple Geometry

see Pt.java

see Line.java

see Polygon.java

see Segment.java

Contest Algorithms:14. CG Basics 3

y = mx + c m = gradient; c = intercept on y-axis

Ax + By + C = 0 // not the same 'c' gradient = -A/B; intercept = -C/B

A line with gradient m that passes through the point (a,b) as the equation:

(y – b) = m(x – a)

Line Equationsgradient (slope) = m

c

Contest Algorithms:14. CG Basics 4

A line can be defined by two points: (a,b) and (s,t)

The gradient m = (t-b)/(s-a) Using y = mx + c, and one of the points,

the intercept c = b – (m*a)

(a, b)

(s, t)

Other Helpful Formulas

Length of line segment between P1 and P2:

L = sqrt[ (x2-x1)2 + (y2-y1)2 ]

Midpoint of a line segment between P1 and P3:

P2 = ( (x1+x3)/2 , (y1+y3)/2 )

Two lines are perpendicular iff

1) m1 = -1/m2

or2) Cosine of the angle between them is 0.

Parametric Form Of a LineGiven points P1 = (x1, y1) and P2 = (x2, y2)

x = x1 + t(x2-x1)

y = y1 + t(y2-y1)

t is called the parameter. When

t = 0 we get (x1,y1)

t = 1 we get (x2,y2)

As 0 < t < 1 we get all the other points on the line segment between (x1,y1) and (x2,y2).

Line Segments & Vectors

p = (x , y )

p = (x , y )

1

2

O = (0, 0) x

y

1 1

2 2

Points (vectors): p , p , p p = p p 1 2 1 2 2 1

p p = (x x , y y ) 1 2

1 2 1 2

Line segment: p p = p p 2 1 1 2

see Vec.java

see Segment.java

Contest Algorithms 8

public class Pt implements Comparable<Pt>{ private static final double EPS = 1e-9;

public double x, y; // 2D (x,y)

public Pt() { x = y = 0.0; }

public Pt(double x, double y) { this.x = x; this.y = y; }

public String toString() { return String.format("(%.3f, %.3f)", x, y); }

public boolean equals(Pt p2) { return ((Math.abs(x - p2.x) < EPS) && (Math.abs(y - p2.y) < EPS)); } : : // many more methods} // end of Pt class

The Pt ClassPt()Pt(double x, double y)

String toString()boolean equals(Pt p2)int compareTo(Pt p)Pt rotate(double theta)Pt translate(Vec v)double dist(Pt p2)double distSqr(Pt p2)double angle()double angle(Pt b)void setSegment(Segment s)Segment getSegment()boolean isLeft()boolean isRight()

// static methodsstatic double angle(Pt a, Pt orig, Pt b)static int ccw(Pt p, Pt q, Pt r)static boolean collinear(Pt p, Pt q, Pt r)static Pt linesIntersect(Pt p1, Pt p2, Pt p3, Pt p4)static double distToLine(Pt p, Pt a, Pt b, Pt c)

Contest Algorithms:14. CG Basics 9

public class Line{ private static final double EPS = 1e-9; public double a, b, c; // 2D // using the line definition: ax + by + c = 0

public Line(double a, double b, double c) { this.a = a; this.b = b; this.c = c; }

public Line(Pt p1, Pt p2) { if (Math.abs(p1.x - p2.x) < EPS) { a = 1; b = 0; c = -p1.x; } else { a = -(p1.y - p2.y) / (p1.x - p2.x); b = 1; c = -(a * p1.x) - p1.y; } } // end of Line() ; // many more methods} // end of Line class

The Line ClassLine(double a, double b, double c)Line(Pt p1, Pt p2)Line(Pt p, double m)

String toString()double angle()double gradient()double value(Pt p)double value(double x, double y)Pt ptForX(double x)Pt ptForY(double y)boolean contains(Pt p)boolean isPointOnLeft(Pt p)boolean isPointOnRight(Pt p)boolean areParallel(Line l2)boolean areSame(Line l2)Pt getIntersect(Line l2)Pt closestPoint(Pt p)Pt reflectionPoint(Pt p)Line perpendicular(Pt p)

Contest Algorithms:14. CG Basics 10

public class Segment{ private static final double EPS = 1e-9; public Pt p1, p2; private double length; private Line line;

public Segment(Pt p1, Pt p2) { this.p1 = p1; this.p2 = p2; length = p1.dist(p2); line = new Line(p1, p2); }

public double length() { return length; }

public Line line() { return line; } : // many more methods}

The Segment Class Segment(Pt p1, Pt p2)

double length()Line line()String toString()Pt middle()double angle()double minX()double minY()double maxX()double maxY()Pt ptForX(double x)Pt ptForY(double y)boolean areParallel(Segment seg)boolean areSame(Segment seg)boolean onSegment(Pt p)double dist(Pt p)Pt closestPoint(Pt p)double dist(Segment seg)Pt getIntersect(Segment seg)boolean intersects(Segment seg)Pt getIntersect(Line l2)boolean contains(Pt p)

// static methodsstatic boolean segmentsIntersect( Pt p1, Pt p2, Pt p3, Pt p4)static boolean onSegment(Pt p, Pt q, Pt mid)

Contest Algorithms:14. CG Basics 11

public class Vec{ private static final double EPS = 1e-9;

public double x, y; // 2D; not Java's Vector public Vec(double x, double y) { this.x = x; this.y = y; }

public Vec(Pt a, Pt b) { x = (b.x - a.x); y = (b.y - a.y); }

public Vec scale(double s) { return new Vec(x*s, y*s); }

public double angle() { return Math.atan2(y, x); }

: // more methods} // end of Vec class

The Vec ClassVec(double x, double y)Vec(Pt a, Pt b)

String toString()Vec scale(double s)double angle()double norm()double normSq()double dot(Vec b)double cross(Vec b)double getAngle(Vec v2)

Contest Algorithms:14. CG Basics 12

public class Polygon{ private static final double EPS = 1e-9; private ArrayList<Pt> pts; // 2D

public Polygon(Pt[] ptsArr) { pts = new ArrayList<Pt>(); for (int i=0; i < ptsArr.length; i++) pts.add(ptsArr[i]); pts.add(ptsArr[0]); // loop back so polygon is closed } // pts[0] = pts[n-1]

public int getSize() { return pts.size(); }

public Pt getPoint(int i) { if ((i < 0) || (i > pts.size()-1)) { System.out.println("Index "+i+" is out of range"); return null; } else return pts.get(i); } // end of getPoint()

: // more methods} // end of Polygon class

The Polygon ClassPolygon(Pt[] ptsArr)

int getSize()Pt getPoint(int i)String toString()double perimeter()double area()Pt center()boolean isConvex()boolean inPolygon(Pt pt)Polygon convexHull()

// static methods for trianglesstatic double perimeter(double ab, double bc, double ca)static double perimeter(Pt a, Pt b, Pt c)static double area(double ab, double bc, double ca)static double area(Pt a, Pt b, Pt c)static boolean canFormTriangle(double a, double b, double c)

Contest Algorithms:14. CG Basics 13

Prefer test (predicates) over 'exact' numerical answers

Avoid floating point ops (e.g. division, square root) that can produce numerical inaccuracies

Try to design functionsto use integers mine use double which is bad style it means the code must test for floating point equality

using |a ‐ b| < EPS instead of a == b

Avoid Float Answers

Contest Algorithms:14. CG Basics 14

public boolean equals(Pt p2) // in Pt class { return ((Math.abs(x - p2.x) < EPS) && (Math.abs(y - p2.y) < EPS)); }

Usage:Pt pt1 = new Pt(2,3);Pt pt2 = new Pt(); // (0,0)if (pt1.equals(pts)) ...

Compare Two Points

Distance between two Points

public double dist(Pt p2) // implements Euclidean distance { return Math.hypot(x - p2.x, y - p2.y); }

Square root is slow and imprecise If we only need to check whether the distance is less

than some certain length, say R, then use: double dx = x - p2.x; double dy = y - p2.y; if ((dx*dx + dy*dy) < R*R) ...

double d = pt1.dist(pt2);

Angle

Given a point (x, y), find its angle about the origin (conventionally counterclockwise)

Answer should be in the range (-π, π]

16

(x, y)

θ

tan θ = y/x

Do not use Math.atan() it cannot distinguish between angles in the first and third

quadrants and in the second or fourth quadrants. it also fails when y == 0

Use Math.atan2(y, x) it returns a radian value between π and –π, and will not

crash if y == 0 note the argument order

17

Math.atan2(), not atan()

public double angle() // in Pt class { return Math.atan2(y, x); }

Angle between Two Points

Find the minor angle (i.e. <= π) between two points a and b.

Solution #1: use atan2() for each point, then subtract Solution #2: use the dot product (see next)

18

a

b

Contest Algorithms:14. CG Basics 19

There are three test programs: PointsLinesTest.java PolygonTests.java TriangleTests.java

You should look at them to see how the Pt, Line, Segment, Vec, and Polygon classes can be used.

Test Programs

Given the two vectors a = <a1, a2, a3> and b = <b1, b2, b3> then the dot product is

a· b = a1*b1 + a2*b2 + a3*b3

Example a = <0, -3, 7>, b = <2, 3, 1> a· b = 0*2 + -3*3 + 7*1 = 9 – 7 = 2

2. Dot (Scalar) Product

Dot Product as Geometry

a b = |a| |b| cos θ

The dot product is the product of the magnitudes of the two vectors a and b and the cosine of the angle between them.

The angle between a and b is:Θ = cos-1((a b) / |a||b|)

Determine the angle between a = <3, -4, -1> and b = <0, 5, 2>

Dot product a· b = -22, |a| = , |b| = The angle is: = = -0.8011927 θ = cos-1(-0.8011927) = 2.5 radians

= 143.24 degrees

Angle Example

Contest Algorithms:14. CG Basics 23

public double angle(Pt b) // in Pt class { Vec oa = new Vec(new Pt(), this); Vec ob = new Vec(new Pt(), b); return Math.acos( oa.dot(ob)/(oa.norm()*ob.norm())); } // end of angle()

Code

public double dot(Vec b) // in Vec class { return ((x * b.x) + (y * b.y)); }

public double norm() { return Math.sqrt(normSq()); }

public double normSq() { return (x * x) + (y * y); }

Pt pt = new Pt(2,2);Pt pt2 = new Pt(0,6);System.out.println("Angle: " + Math.toDegrees( pt.angle(pt2))); // 45 degrees

Contest Algorithms:14. CG Basics 24

double theta = 120.0; System.out.println(theta + " degrees is " +  Math.toRadians(theta) + " radians"); theta = 1.312; System.out.println(theta + " radians is " + 

Math.toDegrees(theta) + " degrees"); 

The output: 120.0 degrees is 2.0943951023931953 radians

1.312 radians is 75.17206272116401 degrees

Degrees ↔ Radians

Or use printf() and "%.3f"e.g. see Pt.toString()

It can be used to get the projection (length) of vector a onto vector b. 

Uses of Dot Product

Given two vectors a = <a1, a2, a3> and b = <b1, b2, b3> then the cross product is

a x b = <a2*b3 – a3*b2, a3*b1 – a1*b3, a1*b2 – a2*b1>This can be written as a determinant: This expands to i - + k

3. Cross (Vector) Product

a = <2, 1, -1> and b = <-3, 4, 1>

Calculate a x b i - + kso i - + k

= 5 i + j + 11 k = <5, 1, 11>

Cross Product Example

The cross product a × b is defined as a vector c that is perpendicular to both a and b, with a direction given by the right-hand rule (the unit vector n) and a magnitude equal to the area of the parallelogram that the vectors span.

Cross Product as Geometry

the area of the parallelogram.

a b = |a| |b | sin θ n

counter-clockwise

Why is |a x b| an area?

a

b

θ

|b| sin θ

|a|

|a x b| = |a||b| sin(θ)so θ = sin-1((a x b) / |a||b|)

What is the angle between a = <2, 1, -1> and b = <-3, 4, 1> (from the last example)?

a x b = 5 i + j + 11 k |a x b| = = 12.124 |a| = (4 + 1 + 1)1/2 = 2.450 |b| = (9 + 16 + 1)1/2 = 5.099

so θ = sin-1(12.124/(2.450*5.099)) = 76.05 degreesor perhaps 180 - 76.05 = 103.95

Angle Example

Contest Algorithms:14. CG Basics 31

public double cross(Vec b) // in the Vec class { return ((x * b.y) - (y * b.x)); }

public double getAngle(Vec v2) { double cross = cross(v2); double sine = cross/(norm()*v2.norm()); // correct any numerical inaccuracies double angle = (sine >= 1) ? Math.PI/2 : Math.asin(sine); double dot = dot(v2); if (dot < 0) angle = Math.PI - angle; if (cross < 0) angle = - angle; return angle; } // end of getAngle()

Code

Contest Algorithms:14. CG Basics 32

Vec v1 = new Vec( new Pt(2,2), new Pt(4,4)); Vec v2 = new Vec( new Pt(2,2), new Pt(2,6)); System.out.println("Angle between vectors v1 and v2: " + Math.toDegrees( v1.getAngle(v2))); // prints 44.9999999999 (really 45)

Usage

(2,2)

(4,4)

(2,6)

45º

You can use the cross product of the vectors a and b to generate a perpendicular vector, which is the normal to the plane defined by a and b.

Normals are very useful when calculating things like lighting in 3D computer games, and up/down in FPSs.

Uses of Cross Product

Suppose we have three vectors a, b, c which form a 3D figure like so:

Geometric Properties

ba

c

Area of the parallelogram of the front face of the object is: area = | a x b |

Volume of the parallelepiped (the entire object) is: volume = |a · (b x c) |

If the volume == 0 then it must mean that all three vectors lie in the same plane

in terms of the box diagram, it means that |a| is 0 units above the b x c face

Area and Volume

Why is |a · (b x c) | a volume? Geometric view:

Scalar Triple Product: a · (b x c)

h = |a| cos α

b x c

α

Determine if the vectors a = <1, 4, -7>, b = <2, -1, 4>, and c = <0, -9, 18> lie on the same plane.

i - + k = 18i - 36j - 18k = <18, -36, -18> a · (b x c) = <1, 4, -7> · <18, -36, -18> = 1*18 + 4*-36 + 7*18 = 18 – 144 + 126 = 0 volume = |a · (b x c) | = 0, which means that all 3

vectors do lie on the same plane.

Example

A basic geometric function: Returns 1 if the points are in

counter-clockwise order (ccw) Returns -1 if the points are in

clockwise order (cw) Returns 0 if the points are

collinear

ccw() utilises cross product.

4. The ccw() Function

2

01

ccw(p0, p1, p2) returns 1

Turning of Consecutive Segments

Counterclockwise Clockwise No turn (collinear)

p

p

p

0

1

2

p

p

p0

1

2p p

p0

1 2

p p p p > 00 1 0 2 p p p p < 00 1 0 2p p p p = 00 1 0 2

Segments p p and p p . Move from p to p then to p . 0 1 1 2 0 1 2

Contest Algorithms:14. CG Basics 40

public static int ccw(Pt p, Pt q, Pt r) /* returns 0, 1, or -1 in Pt class 0 if p-->r and p-->q are collinear 1 if p--> r is left (counter-clockwise) of p-->q -1 if p--> r is right (clockwise) of p-->q */ { Vec v1 = new Vec(p,q); Vec v2 = new Vec(p,r); double cross = v1.cross(v2); if (Math.abs(cross) < EPS) return 0; else if (cross > 0) return 1; else return -1; } // end of ccw()

Codep

q

r

?

System.out.println("ccw value (2,2),(4,4),(2,6): " + Pt.ccw( new Pt(2,2), new Pt(4,4), new Pt(2,6)));

(2,2)

(4,4)

(2,6)

45º

Contest Algorithms:14. CG Basics 41

Intersection of 2 lines in y=ax+b form

Intersection of 2 lines in ax+by +c = 0 form

Intersection of 2 lines defined by four points, two for each line

4. Intersection of Two Lines (in 2D)

Contest Algorithms:14. CG Basics 42

Lines are: y = a1x + b1

y = a2x + b2

and neither is vertical

The lines intersect if the slopes are different (a1 ≠ a2), and the intersection is:

xi = (b2-b1)/(a1-a2) yi = a1xi + b1

Intersection of Lines in y=ax+b form

Contest Algorithms:14. CG Basics 43

Lines are: a1x+b1y+c1 = 0 a2x+b2y+c2 = 0

The lines intersect only if a1b2≠a2b1. The intersection point is:

y = (c1a2- c2a1)/(a1b2-a2b1) x = -1/a1 - b1y/a1

Intersection of Lines in ax+by +c = 0 form

Used by Line.java

Contest Algorithms:14. CG Basics 44

(x1,y1) and (x2,y2) belonging to the first line (x3,y3) and (x4,y4) belonging to the second line

The intersection is given by solving the following equations:

Intersection of Lines defined by 4 Points

xi,yi is the intersection point

Contest Algorithms:14. CG Basics 45

The lines intersect if D ≡ (x1-x2)(y3-y4) - (y1-y2)(x3-x4) ≠ 0

The intersection point is: xi = [ (x3 - x4)(x1y2 – y1x2) - (x1 – x2)(x3y4 – y3x4) ] / D yi = [ (y3 - y4)(x1y2 – y1x2) - (y1 – y2)(x3y4 – y3x4) ] / D

Contest Algorithms:14. CG Basics 46

// in Pt class public static Pt linesIntersect(Pt p1, Pt p2, Pt p3, Pt p4) // p1 and p2 are on the first line; p3 and p4 are on the second line { double d = (p1.x-p2.x)*(p3.y-p4.y) - (p1.y-p2.y)*(p3.x-p4.x); if (d == 0) return null; double xi = ((p3.x - p4.x)*(p1.x*p2.y - p1.y*p2.x) - (p1.x - p2.x)*(p3.x*p4.y - p3.y*p4.x) )/d; double yi = ((p3.y - p4.y)*(p1.x*p2.y - p1.y*p2.x) - (p1.y - p2.y)*(p3.x*p4.y - p3.y*p4.x) )/d; return new Pt(xi,yi); } // end of linesIntersect()

Code

Contest Algorithms:14. CG Basics

System.out.println("Intersection of lines (2,2)--(4,4) and (2,4)--(4,2): " + Pt.linesIntersect( new Pt(2,2), new Pt(4,4), new Pt(2,4), new Pt(4,2))); // prints (3.000, 3.000)

Usage

47

(4,4)(4,2)

(2,4)(2,2)

Contest Algorithms:14. CG Basics 48

Line ln1 = new Line( new Pt(2,2), new Pt(4,4));Line ln2 = new Line( new Pt(2,4), new Pt(4,2));System.out.println("2. Intersection of lines: " + ln1.getIntersect(ln2)); // (3.000,3.000)

Usage 2

Contest Algorithms:14. CG Basics 49

// in the Line class public Pt getIntersect(Line l2) // returns intersection Pt if two lines intersect { if (areParallel(l2)) return null;

// solve system of 2 linear algebraic equations // with 2 unknowns double x = ((l2.b * c) - (b * l2.c)) / ((l2.a * b) - (a * l2.b));

// special case: test for vertical Line to // avoid division by zero double y; if (Math.abs(b) > EPS) y = -((a * x) + c); else y = -((l2.a * x) + l2.c); return new Pt(x,y); } // end of getIntersect()

Code

I cannot use Pt.linesIntersect() since my Line class does not store point information

5. Intersection of two Line Segments Method 1:

1. Assume the segments are lines (i.e. no endpoints)2. Find the intersection of the two lines3. Check whether the intersection point lies between the

endpoints Method 2:

First check whether the two segments intersect A lot easier than step 3 in method 1. See next slide

If so, find the intersection as in step 2 of method 1

50

Do two line segments and intersect ?

Do Two Line Segment Intersects?

p4

p3p1

p2

• Boundary cases must be considered.

A segment straddles a line if point p1 lies on one side of the line and point p2 lies on the other side.

a man straddlinga motorbike

p1

p2

A boundary case arises if p1 or p2 lies directly on the line.

p1

p2

Contest Algorithms 54

public static boolean segmentsIntersect(Pt p1, Pt p2, Pt p3, Pt p4) // do the line segments p1--p2 and p3--p4 intersect? in Segment class { int d1 = Pt.ccw(p3, p4, p1); int d2 = Pt.ccw(p3, p4, p2); int d3 = Pt.ccw(p1, p2, p3); int d4 = Pt.ccw(p1, p2, p4);

if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) return true;

if (d1 == 0 && Pt.onSegment(p3, p4, p1)) return true; if (d2 == 0 && Pt.onSegment(p3, p4, p2)) return true; if (d3 == 0 && Pt.onSegment(p1, p2, p3)) return true; if (d4 == 0 && Pt.onSegment(p1, p2, p4)) return true; return false; } // end of segmentsIntersect()

Code

linesstraddle

checkboundarycases

p

p

1

2

p

p

3

4

p 1

p2

p3

p4

public static boolean onSegment(Pt p, Pt q, Pt mid) // is mid on the line between p and q? { if ( (mid.x <= Math.max(p.x, q.x)) && (mid.x >= Math.min(p.x, q.x)) && (mid.y <= Math.max(p.y, q.y)) && (mid.y >= Math.min(p.y, q.y)) ) return true; return false; } // end of onSegment()

public boolean intersects(Segment seg) { return Segment.segmentsIntersect(p1, p2, seg.p1, seg.p2); }

General Cased1 = ccw(p3, p4, p1)d2 = ccw(p3, p4, p2)

d3 = ccw(p1, p2, p3)d4 = ccw(p1, p2, p4)

p

p

1

2

p

p

3

4

d1

d2

p

p

1

2

p

p

3

4d3

d4

if ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) &&

((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0)) return true

d1 and d2 must go opposite ways

d3 and d4 must go opposite ways

Non-intersection Example

p2

p1p4

p3

d1 = ccw(p3, p4, p1)d2 = ccw(p3, p4, p2)

d3 = ccw(p1, p2, p3)d4 = ccw(p1, p2, p4)

d3 and d4 do not go opposite ways

d3

d4

Contest Algorithms:14. CG Basics 58

Segment seg = new Segment( new Pt(2,2), new Pt(4,4));System.out.println("Segment: " + seg);System.out.println("Intersection of segs (2,2)--(4,4) and (2,4)--(4,2): " + seg.intersects( new Segment(new Pt(2,4), new Pt(4,2))) ); // true

System.out.println("Intersection of segs (2,2)--(4,4) and (2,3)--(4,5): " + seg.intersects( new Segment(new Pt(2,3), new Pt(4,5))) ); // false

Usage

(4,4)(4,2)

(2,4)(2,2)

(4,4)

(4,5)

(2,3)(2,2)

Contest Algorithms:14. CG Basics 59

System.out.println("Intersection of segs (2,2)--(4,4) and (2,4)--(4,2): " + seg.getIntersect( new Segment(new Pt(2,4), new Pt(4,2))) ); // (3.000,3.000)

// in Segment class public Pt getIntersect(Segment seg) { if (intersects(seg)) { // check if segments intersect Line l2 = new Line(seg.p1, seg.p2); return line.getIntersect(l2); // use line intersection to get pt } else return null; } // end of getIntersect()

Finding the Intersection

Given a point and a line, determine the shortest distance between them.

6. Shortest Distance Between a Point and a Line

P3

P1P2

h

One way is to find the intersection between the line and the line perpendicular to the P1—P2 line which goes through P3.

using the dot product

P

Contest Algorithms:14. CG Basics 61

P3

P1P2

P

gradient == m

gradient == 1/m

One way is to find the intersection between the line and the line perpendicular to the P1—P2 line which goes through P3.

Contest Algorithms:14. CG Basics 62

// in the Line class public Pt closestPoint(Pt p3) // find the closest pt on the line to p3 { if (Math.abs(b) < EPS) // special case 1: vertical Line return new Pt(-c, p3.y); if (Math.abs(a) < EPS) // special case 2: horizontal Line return new Pt(p3.x, -c);

Line perp = new Line(p3, -1/gradient()); // perpendicular (normal line) // intersect Line with this perpendicular; // the intersection is the closest Pt, P return getIntersect(perp); } // end of closestPoint()

Code

Contest Algorithms:14. CG Basics 63

Shortest Distance for a Line Segment

Given a point and a line segment, determine the shortest distance between them.

P1P2

h

The equation of a line defined through two points P1 (x1,y1) and P2 (x2,y2) is P = P1 + u (P2 - P1)with 0 ≤ u ≤ 1 (for line segments)

P3

P

The point P3 (x3, y3) is closest to the line at the tangent to the line which passes through P3, that is, the dot product of the tangent and line is 0, thus

(P3 - P) (P2 - P1) = 0

Substituting the equation of the line gives: [P3 - P1 - u(P2 - P1)] (P2 - P1) = 0

Solving this gives the value of u:

Uses a (b+c) = (a b) + (a c)

cos 90 == 0

Substituting this into the equation of the line gives the point of intersection (x, y) of the tangent as:

x = x1 + u (x2 - x1)y = y1 + u (y2 - y1)

The distance between the point P3 and the line is the distance between (x, y) and P3.

// in the Segment class public Pt closestPoint(Pt p3) /* returns the point on the line segment which is closest to the point p3 */ { Vec vp = new Vec(p1, p3); Vec v = new Vec(p1, p2); // change line segment into vector double u = vp.dot(v) / v.normSq(); // projection

if (u < 0.0) return p1; // closer to p1 else if (u > 1.0) { return p2; // closer to p2 } else // some pt along p1--p2 from p1 return new Pt(p1.x + u*v.x, p1.y + u*v.y); } // end of closestPoint()

Code

Contest Algorithms:14. CG Basics 67

Segment segLine = new Segment( new Pt(2,2), new Pt(4,4));Pt p3 = new Pt(2,4);Pt p = segLine.closestPoint(p3);double d = p3.dist(p);System.out.println("Closest Pt to (2,4) on seg (2,2)--(4,4)): " + p + ", dist = " + d); // (3,3) , √2

Usage

(4,4)

(2,4)(2,2)

(3,3)

√2

7. Area of a Triangle

Area = Base * Height / 2

Area = a * b * sin(C) / 2

Heron’s formula: Area = sqrt( s(s-a)(s-b)(s-c) ) where s = (a+b+c)/2, the semi-perimeter

68

A

B

C

a

b

c

static methods in Polygon.java

public static double area(double ab, double bc, double ca) { double s = 0.5 * Polygon.perimeter(ab, bc, ca); return Math.sqrt(s) * Math.sqrt(s-ab) * Math.sqrt(s-bc) * Math.sqrt(s-ca); }

Area of a Triangle Given as Points

What if only the vertices of the triangle are given? e.g. (x1, y1), (x2, y2), (x3, y3)

Area = abs( x1*y2 + x2*y3 + x3*y1 - x2*y1 - x3*y2 - x1*y3 ) / 2

abs can be omitted if the vertices are in counter-clockwise order.

If the vertices are in clockwise order, the area evaluates to a negative.

69

That hard-to-memorize expression can be drawn as:

Area = ½ * x1 y1

x2 y2

x3 y3

x1 y1

-

+

Contest Algorithms:14. CG Basics 71

Basic Polydon functions: perimeter, area, center point is it convex or concave? does a point lie inside the polygon or not?

More complex functions: convex hull (see next part) triangulation Voronoi diagrams

8. Polygon Functions

Area of a Convex (and Concave) Polygon It turns out the previous formula still works

Area = ½ *

72

(x1, y1)

(x2, y2)

(x3, y3)(x4, y4)

(x5, y5)

x1 y1

x2 y2

x3 y3

x4 y4

x5 y5

x1 y1+

-

Contest Algorithms:14. CG Basics 73

public double area() // in Polygon class // returns the area, which is half the determinant; // works for both convex and concave polygons { double result = 0.0; double x1, y1, x2, y2; for (int i = 0; i < pts.size()-1; i++) { x1 = pts.get(i).x; x2 = pts.get(i+1).x; y1 = pts.get(i).y; y2 = pts.get(i+1).y; result += (x1 * y2 - x2 * y1); } return Math.abs(result)/2.0; } // end of area()

Code

Contest Algorithms:14. CG Basics 74

Pt[] ptsArr = { new Pt(1,1), new Pt(3,3), new Pt(6,1), new Pt(6,6), new Pt(1,6) }; // points, in counter clockwise order

Polygon poly = new Polygon(ptsArr); // last point added to polygon is always copy of first, so that // the shape is closed System.out.println("Perimeter: " + poly.perimeter()); // 21.434System.out.println("Area: " + poly.area()); // 20System.out.println("Is convex: " + poly.isConvex()); // false (P1 is the culprit)

Usage in PolygonTests.java

75

Polygon Coordinates

Contest Algorithms:14. CG Basics

1 2 3 4 5 6 7 8 9

1

23

4

5

678

9

Pt[] ptsArr = { new Pt(1,1), new Pt(3,3), new Pt(6,1), new Pt(6,6), new Pt(1,6) }

Is a Point inside a Convex Polygon?

Given a convex polygon and a point, is the point inside the polygon?

Assume the vertices are given in counterclockwise order for convenience

76

inside

outside

inside (definition may change)

Is a Polygon Convex?

A polygon is convex if and only if every turn (at every vertex) is a left turn

Whether a “straight” turn is allowed depends on the problem definition

ccw() is useful

77

Contest Algorithms:14. CG Basics 78

public boolean isConvex() // in Polygon class /* returns true if we always make a left turn while examining all the edges of the polygon one by one. I assume the points are listed in counter-clockwise order. */ { int sz = pts.size(); if (sz <= 3) // not convex return false; Pt lastPt; for (int i = 0; i < sz - 1; i++) { // compare with the others if ((i+2) == sz) lastPt = pts.get(1); else lastPt = pts.get(i+2); if (Pt.ccw(pts.get(i), pts.get(i+1), lastPt) < 1) // not ccw return false; // this polygon is concave } return true; } // end of isConvex()

Code

Is a Point inside a Polygon?

Compute the angle between pt and consecutive vertices in the polygon, pi and pi+1.

The sum for all the vertices should be (close to) 2π if pt is inside the polygon.

79

pt

pi

pi+1

θ

Contest Algorithms:14. CG Basics 80

public boolean inPolygon(Pt pt) // in Polygon class // returns true if Pt p is inside either convex/concave polygon pts { if (pts.size() == 0) return false;

double sum = 0; // assume first vertex = last vertex for (int i = 0; i < pts.size()-1; i++) { if ( Pt.ccw(pt, pts.get(i), pts.get(i+1)) == 1) sum += Pt.angle(pts.get(i), pt, pts.get(i+1)); // left turn/ccw else sum -= Pt.angle(pts.get(i), pt, pts.get(i+1)); // right turn/cw } return (Math.abs(Math.abs(sum) - 2*Math.PI) < EPS); } // end of inPolygon()

Code

Contest Algorithms:14. CG Basics 81

Pt P6 = new Pt(3, 2); System.out.println("Point P6 is inside: " + poly.inPolygon(P6)); // false

Pt P7 = new Pt(3, 4);System.out.println("Point P7 is inside: " + poly.inPolygon(P7)); // true

Usage in PolygonTests.java

Contest Algorithms:14. CG Basics 82

https://github.com/mikhaildubov/ Computational-geometry

segments intersection, convex hull, closest points, triangulation, Halfplanes, Voronoi diagrams

https://github.com/bkiers/CompGeom Graham scan (convex hulls), rotating calipers, closest pair of

points, Shamos-Hoey algorithm, Bentley-Ottmann (sweep line)

9. Some Other CG Code Sources

Contest Algorithms:14. CG Basics 83

http://www.sanfoundry.com/java-programming-examples-computational-geometry-problems-algorithms/

a lot of examples still to be uploaded

https://tutorial92.wordpress.com/2012/08/17/ geometry-library-java/