UVa OJ 137-Polygons (Polygons)

Source: Internet
Author: User

Time limit: 3.000 seconds
Time Limit: 3.000 seconds

Problem
Problem

Given two convex polygons, they may or may not overlap. if they do overlap, they will do so to differing degrees and in different ways. write a program that will read in the coordinates of the corners of two convex polygons and calculate the 'exclusive or 'of the two areas, that is the area that is bounded by exactly one of the polygons. the desired area is shaded in the following disince:
Two convex polygon that may overlap with each other are given. If there is overlap, the overlapping angles and directions are different. You need to write a program to read the coordinates of each corner of Two convex polygon, and calculate the area of the region obtained by the two "exclusive or, that is, only the area of one polygon exists in all areas of the two. Shows the required area:

 

 

Input
Input

Input will consist of pairs of lines each containing the number of vertices of the polygon, followed by that sort pairs of integers representing the x, y coordinates of the corners in a clockwise ction. all the coordinates will be positive integers less than 100. for each pair of polygons (pair of lines in the data file), your program shocould print out the desired area correct to two decimal places. the input will end with a line containing a zero (0 ).
The input consists of multiple rows, each of which is a group of two rows. The first number in each row is the number of vertices of the polygon, followed by x and y coordinate values of Multiple Integer groups, which are arranged clockwise. All coordinates are positive integers and smaller than 100. For each two polygon (each two rows of input data), your program should print the required area and keep 2 decimal places. The last line is 0.

 

Output
Output

Output will consist of a single line containing the desired area written as a succession of eight (8) digit fields with two (2) digits after the decimal point. there will not be enough cases to need more than one line.
Only one row of output results. The calculated area is output in 8 digits, and only two digits are retained after the decimal point ). There won't be too many test cases, so one row is enough.

 

Sample input
Input

3 5 5 8 1 2 3
3 5 5 8 1 2 3
4 1 2 1 4 5 5 2
6 6 3 8 2 8 1 4 1 4 2 5 3
0

 

Sample output
Sample output

△△△△ 0.00 △△△ 13.50

 

Where △represents a single space.
Each triangle represents a space.

 

Analysis
Analysis

The problem solving process is very complex. It is difficult to write a completely correct program from scratch. There are many algorithms involved, and there are many special cases. If an error occurs in one step in the middle, it is difficult to locate the error. Therefore, we do not recommend that you use this question.

The main algorithms involved in this question are (all on a two-dimensional plane): determining the intersection of a line segment, finding the intersection of a line segment, finding the convex hull of a point set, determining the point inside a polygon, and finding the area of a polygon. I used a simple idea to solve this problem. I used mature algorithms I have previously written. It may be a bit violent, but it can ensure no error.

First, the area of the Two convex polygon can be calculated according to the following formula:

Then obtain the points of the two polygon inside each other and add the intersection vertex array. Here we use the algorithm to determine the point in the polygon. First, make sure that the points on the convex polygon are given clockwise or counterclockwise. For each point (x0, y0 ), the starting point pi of each line segment vi on the polygon forms the vector vsi. If there is a vi × vsi <0 (greater than the number when it is counterclockwise), the point is not in the polygon. The principle is that if a vertex is located in it, the angle between the vector formed by each vertex on the polygon and the edge starting from the vertex must be less than 180 degrees.

Next, calculate the intersection of each line segment of the two polygon, obtain all the intersections (including overlapping vertices), and add the intersection vertex array. For the algorithm used here, see the positional relationship (intersection) between two line segments in the plane and the intersection.

Find the convex hull of the intersection vertex array. For more information, see solve the convex hull problem using the Graham's Scan method. In fact, the intersection vertices obtained at this time are convex packets, but they are not arranged in order and there may be many repeated vertices. Therefore, we can use the convex packet algorithm to sort them again.

The result is calculated by subtracting the sum of two polygon areas from the intersection area by two times. The whole process is clearly explained in the comments of the Code. Check the code.

In fact, there is an O (n) algorithm for finding all the vertices of the intersection, that is, first finding the first vertex of the intersection of two polygon, and then rotating it clockwise, add a point with more rotation in the next vertex or intersection of the two polygon. In this way, the intersection vertices in clockwise order can be obtained at one time. However, the implementation of such algorithms is complicated, and there are many special cases to deal with. More importantly, I have no mature implementation at hand. If I rashly apply it to such complicated algorithm questions, it is likely that the AC will never be available and the error cannot be found.

If you have a better idea, I hope you can give me some advice.

 

Solution
Answer
# Include <algorithm> # include <iostream> # include <vector> # include <cmath> using namespace std; struct POINTF {float x; float y ;}; // ensure accuracy, if the difference between two obscenity points is less than 0.0001, it is considered Equal to bool Equal (float f1, float f2) {return (abs (f1-f2) <1e-4f );} // determine whether two points are Equal bool operator = (const POINTF & p1, const POINTF & p2) {return (Equal (p1.x, p2.x) & Equal (p1.y, p2.y);} // compare the coordinates of two points. Compare the coordinates of x first. If the coordinates are the same, compare bool operator> (const POINTF & p1, const POINTF & P2) {return (p1.x> p2.x | (Equal (p1.x, p2.x) & p1.y> p2.y ));} // calculate the two-vector outer product float operator ^ (const POINTF & p1, const POINTF & p2) {return (p1.x * p2.y-p1.y * p2.x );} // determine the relationship between the two line segments and obtain the intersection (if any ). // Overlap: Full coincidence (6), one endpoint coincidence and collinearity (5), partial coincidence (4) // no coincidence: intersection of the two ends (3 ), intersection on line (2), orthogonal (1), zero (0), parameter error (-1) int Intersection (POINTF p1, POINTF p2, POINTF p3, POINTF p4, POINTF & Int) {// ensure parameter p1! = P2, p3! = P4if (p1 = p2 | p3 = p4) {return-1; // return-1 indicates that at least one line segment is overlapped at the beginning and end, cannot constitute a line segment} // to facilitate calculation, ensure that the start point of each line segment is before and the end point is behind. If (p1> p2) {swap (p1, p2) ;}if (p3> p4) {swap (p3, p4 );} // obtain the outer product of two vectors, such as POINTF v1 = {p2.x-p1.x, p2.y-p1.y}, v2 = {p4.x-p3.x, p4.y-p3.y}. // obtain the outer product of two vectors, in parallel, the outer product is 0 float Corss = v1 ^ v2; // determines whether the two line segments completely overlap if (p1 = p3 & p2 = p4) {return 6 ;} // if the starting point is overlapped if (p1 = p3) {Int = p1; // if the starting point is overlapped and the collinearity (parallel) returns 5; if the starting point is not parallel, it is handed over to the endpoint, returns 3 return (Equal (Corss, 0 )? 5: 3);} // if the end point is overlapped if (p2 = p4) {Int = p2; // if the end point is overlapped and the end point is collocated (parallel), return 5; if it is not parallel, it is handed over to the endpoint and 3 return (Equal (Corss, 0 )? 5: 3);} // if the two ends are connected at the beginning and end if (p1 = p4) {Int = p1; return 3;} if (p2 = p3) {Int = p2; return 3;} // After the above judgment, the first and last vertices are all out of phase duplicates. // The line segments are sorted by the start and end vertices. If the starting point of Line Segment 1 is large, the two line segments are exchanged if (p1> p3) {swap (p1, p3); swap (p2, p4 ); // update the previously calculated vector and its outer product swap (v1, v2); Corss = v1 ^ v2;} // process parallel conditions of two line segments if (Equal (Corss, 0 )) {// perform the outer product of the vectors v1 (p1, p2) and vs (p1, p3) to determine whether or not POINTF vs = {p3.x-p1.x, p3.y-p1.y} Are collocated }; // if the outer product is 0, the two parallel lines are in the same line. if (Equal (v1 ^ vs, 0 )) {// if (p2> p3) {Int = p3; return 4; // return value 4 indicates that the part of the line segment is overlapped} // if the three points are not collocated, the two parallel lines are not collocated. // Returns 0 if there are no parallel lines that are not collocated or collocated but do not overlap.} // if the following are not parallel lines, perform the fast Rejection Test first. // The x coordinate is ordered, can be directly compared. The y coordinate must first calculate the maximum and minimum float ymax1 = p1.y, ymin1 = p2.y, ymax2 = p3.y, ymin2 = p4.y; if (ymax1 <ymin1) {swap (ymax1, ymin1) ;}if (ymax2 <ymin2) {swap (ymax2, ymin2) ;}// if the rectangle with two linelines as diagonal lines does not intersection, if (p1.x> p4.x | p2.x <p3.x | ymax1 <ymin2 | ymin1> ymax2) {return 0 ;} // The following cross-site test POINTF vs1 = {p1.x-p3.x, p1.y-p3.y}, vs2 = {p2.x-p3.x, p2.y-p3.y}, POINTF vt1 = {p3.x-p1.x, p3.y-p1.y}, vt2 = {p4.x-p1.x, P4.y-p1.y}; float s1v2, s2v2, t1v1, t2v1; // determine whether to submit the data to the online if (Equal (s1v2 = vs1 ^ v2, 0) based on the outer product result) & p4> p1 & p1> p3) {Int = p1; return 2;} if (Equal (s2v2 = vs2 ^ v2, 0) & p4> p2 & p2> p3) {Int = p2; return 2;} if (Equal (t1v1 = vt1 ^ v1, 0) & p2> p3 & p3> p1) {Int = p3; return 2;} if (Equal (t2v1 = vt2 ^ v1, 0) & p2> p4 & p4> p1) {Int = p4; return 2;} // not submitted online, determine whether the intersection is if (s1v2 * s2v2> 0 | t1v1 * t2v1> 0) {return 0;} // The following is the intersection. For details about the algorithm, see the document // two constant items for calculating the Second-Order Determinant float ConA = p1.x * v1.y-p1.y * v1.x; float ConB = p3.x * v2.y-p3.y * v2.x; // calculates the values of the determine factors D1 and D2. Divide the values by the coefficient determine factors to obtain the intersection coordinate Int. x = (ConB * v1.x-ConA * v2.x)/Corss; Int. y = (ConB * v1.y-ConA * v2.y)/Corss; // returns 1 return 1 orthogonal;} // compares the X axis vector with the X axis vector (1, 0) bool CompareVector (const POINTF & pt1, const POINTF & pt2) {// evaluate the modulo float m1 = sqrt of the vector (pt1.x * pt1.x + pt1.y * pt1.y); Float m2 = sqrt (pt2.x * pt2.x + pt2.y * pt2.y); // obtain the Inner Product float v1 = pt1.x/m1 from the two vectors and (1, 0) respectively, v2 = pt2.x/m2; // If the vector angle is equal, return a value closer to the base point, ordered return (v1 <v2 | v1 = v2 & m1 <m2);} // calculates the convex hull bool CalcConvexHull (vector <POINTF> & Src) {// a vertex set must have at least three vertices to form a polygon if (Src. size () <3) {return false;} // search for the base point vector <POINTF>: iterator I; POINTF ptBase = Src. front (); // set the 1st points to the minimum point for (I = Src. begin () + 1; I! = Src. end (); ++ I) {// if the y value of the current vertex is smaller than the minimum vertex, or the y value is equal, the x value is smaller if (I-> y <ptBase. y | (I-> y = ptBase. y & I-> x> ptBase. x) {// use the current vertex as the minimum vertex ptBase = * I;} // calculates the vector for (I = Src. begin (); I! = Src. end ();) {// exclude vertices that are the same as the base point to avoid the if (* I = ptBase) {I = Src. erase (I);} else {// from the base point to the target point I-> x-= ptBase. x, I-> y-= ptBase. y; ++ I ;}/// sort by the angle between each vector and the abscissa sort (Src. begin (), Src. end (), & CompareVector); // Delete the same vector Src. erase (unique (Src. begin (), Src. end (), Src. end (); // There are at least two vertices left in the vertex set. The polygon if (Src. size () <2) {return false;} // calculates the first and last connected vector for (vector <POINTF>: reverse_iterator ri = Src. rbegin (); ri! = Src. rend ()-1; ++ ri) {vector <POINTF>: reverse_iterator riNext = ri + 1; // vector Triangle Formula ri-> x-= riNext-> x, ri-> y-= riNext-> y ;} // Delete the for (I = Src. begin () + 1; I! = Src. end (); ++ I) {// trace back to delete the vector with the opposite rotation direction, and use the outer product to determine the rotation direction for (vector <POINTF >:: iterator iLast = I-1; iLast! = Src. begin ();) {float v1 = I-> x * iLast-> y, v2 = I-> y * iLast-> x; // If the cross accumulation is greater than 0, then there is no Reverse Rotation // If the cross product is equal to 0, you also need to use inner products to determine whether the direction is inverse if (v1> v2 | (v1 = v2 & I-> x * iLast-> x> 0 & I-> y * iLast -> y> 0 )) {break;} // After deleting the previous vector, update the current vector and connect it to the beginning and end of the previous vector. // vector Triangle Formula I-> x + = iLast-> x, i-> y + = iLast-> y; iLast = (I = Src. erase (iLast)-1 ;}// accumulate all the first and end vectors in sequence and convert them to the coordinate Src. front (). x + = ptBase. x, Src. front (). y + = ptBase. y; for (I = Src. begin () + 1; I! = Src. end (); ++ I) {I-> x + = (I-1)-> x, I-> y + = (I-1)-> y ;} // Add the base point. All the convex packets are computed to complete Src. push_back (ptBase); return (Src. size ()> = 3);} // calculates the float CalcArea (vector <POINTF> & Covex) {float fArea = 0; vector <POINTF>: iterator I, j; // times every vertex of a polygon for (I = Covex. begin (); I! = Covex. end (); ++ I) {// j is the next vertex of I. if (j = I + 1) = Covex. end () {j = Covex. begin ();} // accumulative area fArea + = j-> x * I-> y-I-> x * j-> y;} return fArea/2.0f ;} // determine whether the vertex is inside the polygon bool PointInPolygon (POINTF pt, vector <POINTF> & Poly) {// times every vertex of the polygon for (int I = 0; I <(int) Poly. size (); ++ I) {// j is the next vertex of I, int j = (I + 1) % (int) Poly. size (); // construct the vector POINTF p1 = {pt. x-Poly [I]. x, pt. y-Poly [I]. y}; // construct the vector POINTF from the current vertex to the next Vertex P2 = {Poly [j]. x-Poly [I]. x, Poly [j]. y-Poly [I]. y}; // determine float fCross = p1 ^ p2 Based on the outer product; if (fCross <0) {return false ;}} return true ;} // main function int main (void) {vector <float> Result; // read each group of polygon data cyclically for (int nNum; cin> nNum & nNum! = 0; ++ nNum) {vector <POINTF> Poly1, Poly2; for (POINTF pt; nNum --> 0 & cin> pt. x> pt. y; Poly1.push _ back (pt); cin> nNum; for (POINTF pt; nNum --> 0 & cin> pt. x> pt. y; Poly2.push _ back (pt); // remove the adjacent repeating points unique (Poly1.begin (), Poly1.end (); unique (Poly2.begin (), poly2.end (); if (Poly1.size () <3 | Poly2.size () <3) {printf ("% 8.2f", 0.0f );} // calculate the area of the two polygon and float fAreaUnion = CalcArea (Poly1); fAr EaUnion + = CalcArea (Poly2); vector <POINTF> IntPoly; // Add the point of polygon 1 in polygon 2 to the for (int I = 0; I <(int) poly1.size (); ++ I) {if (PointInPolygon (Poly1 [I], Poly2) {IntPoly. push_back (Poly1 [I]) ;}// Add the point of polygon 2 in polygon 1 to the Intersection Set for (int I = 0; I <(int) Poly2.size (); ++ I) {if (PointInPolygon (Poly2 [I], Poly1) {IntPoly. push_back (Poly2 [I]) ;}// obtain all the intersections of the two polygon, including the overlapped vertices, and add them to the intersection for (int I = 0; I <(int) poly1.size (); ++ I) {for (int j = 0; j <(int) Poly2.size (); ++ j) {POINTF Int; int nr = Intersection (Poly1 [I], Poly1 [(I + 1) % (int) poly1.size ()], Poly2 [j], Poly2 [(j + 1) % (int) Poly2.size ()], Int); if (nr = 6) {IntPoly. push_back (Poly1 [I]); IntPoly. push_back (Poly1 [(I + 1) % (int) Poly1.size ()]);} else if (nr> 0) {IntPoly. push_back (Int) ;}}// calculates the convex hull for the intersection and calculates the float fIntArea = CalcConvexHull (IntPoly )? CalcArea (IntPoly) * 2: 0; // Save the Result. push_back (fAreaUnion-fIntArea);} // output the Result in the format of for (vector <float >:: iterator I = Result. begin (); I! = Result. end (); ++ I) {printf ("% 8.2f", * I) ;}cout <endl; return 0 ;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.