CS-211 Fall 2015 Lab 5 C Control Part II

Background

Last week, we wrote a program to determine if a point was inside the bounding box of a convex polygon. If you remember, we defined a polygon as a list of (x,y) coordinates which represent the verteces of the polygon. You were given the code to read a polygon file, and functions to get information about the polygon.

This week, we will complete the job... determine if the point specified in the program's arguments are actually inside the polygon itself. To illustrate this question, consider the following figure, which shows a triange and a point that is inside the bounding box of that triangle, but is not inside the perimeter of the triangle itself.

The question is, how do we tell the computer how to figure out if the point is inside the perimeter or not?

There are different ways to answer this question, but one easy way to think about this problem is to think of a vertical line that goes through the point in question, like the red line in the following figure.

Notice that the red line intersects exactly two line segments that make up the perimeter of the polygon. If we can determine the (x,y) coordinates of the intersection of this line with the perimeter, that will give us the (x,y) coordinates of the two orange/brown dots in the figure above; namely (1,0) and (1,3.6). Then we can check whether our point, (1,3.9) has a y coordinate between 0 and 3.6. If it does, the point is inside the polygon. If not, the point is outside the polygon. In this case, 3.9 is greater than the higher itersection coordinate of 3.6, so the point is in fact, outside of the triangle.

It turns out that since we are dealing with convex polygons, we can draw a vertical line from a point inside the bounding box of the polygon, and be guaranteed that our line crosses either a segment of the polygon boundary or a vertex of the polygon exactly two times - one low and one high.

We can enumerate the line segments of a polygon if we know its verteces by simply taking two adjaced pairs of vertexes. (Note that the last one is also paired with the first one.) Therefore, if we have verteces from 0 to (n-1), the list of line segments in the perimeter is simply

FromTo
vertex 0 vertex 1
vertex 1 vertex 2
... ...
vertex n-2 vertex n-1
vertex n-1 vertex 0

It's pretty simple to see if our vertical line crosses a particular segment. Just find the lowest X coordinate of the end-points of the line segment, and if our vertical line X is greater than the lower X, but less than the higher X, then our vertical line crosses that segment.

Once we know that our vertical line crosses a particular segment, we can perform iterpolation to determine the Y coordinate of the intersection of our vertical line with the segment. To do so, we can use the following formula, where the line segment goes from (x1,y1) to (x2,y2), and the vertical line is at xq

y_intersect = y1 + (xq-x1) * (y2-y1)/(x2-x1)

If our vertical line goes through a vertex, then the x coordinate of the vertex must match the x coordinate of the vertical line, and the y coodinate of the intersection is simply the y coordinate of that vertex.

Getting Started

You may either continue using the code you created from last week's lab, or download the Professor's solution to last week's lab as a starting point. (If you didn't finish last week's lab, you may want to just download.) If you want to download the Professor's solution, grab lab5.tar.gz and move it into you home directory. Use the command tar -xvzf lab5.tar.gz. This will unpack the tar file and make a new lab5 subdirectory.

The Polygon Functions

The polygon functions are the same as last week, but I've included the documentation here for reference.

The two C files called poly.h and poly.c contain the declarations and definitions for the functions to handle polygons. You will not need to change anything in these files, but you do need to understand how to call these functions. Feel free to look at this code, but there are some things in these files, like C structures and typedefs, which we haven't studied yet... so don't worry if you can't understand everything.

The poly.h file contains everything you need to invoke the polygon functions. Therefore, we #include "poly.h" in our main C file. The function definitions for these files is in the poly.c file. But the important thing is how these functions work.

First, we need to talk about the polygon data type defined in poly.h. We can declare a variable as a polygon, just like declaring a variable as an integer, by using polygon p;. After such a declaration, we can use the variable "p" to hold a polygon. The "makePolygon" function returns a value of the polygon type, so we can do something like p=makePolygon(x). Several other polygon functions require arguments which have a polygon type. We can provide values by using a variable of type polygon, such as: int n=verteces(p);.

Now we can describe te functions themselves

For instance, if I code polygon p=makePolygon("triangle.txt");, then when I invoke printPolygon(p); then the following will get printed to standard output:

verteces: 3
(0.000000,0.000000) (10.000000,0.000000) (0.000000,4.000000)

Also, the value of verteces(p) will be 3; the value of vertexX(p,1) will be 10.0; and the value of vertexY(p,1) will be 0.0. I should also call deletePolygon(p); before I exit.

Using The Makefile

The Makefile is the same as last week as well...

The Makefile file in the lab5 directory contains the recipes to build the C program associated with whose "main" function is in contains.c. To build the contains executable, use the make contains.

The Makefile file contains several other "targets" which allow you to do other things using the make command. The following targets are supported:

Adding to the main function

The file contains.c in the lab5 directory contains the code we used last week to read a polygon definition and determine if a point is inside the boundig box of the polygon. You can assume that the first parameter passed into your program (after the name of the program itself) is the name of a polygon definition file, the second parameter is an x coordinate, and the third parameter is a y coordinate. The second and third parameters make up the coordinate of the point you want to check.

Your main function already performs the following actions...

  1. Checks to make sure three parameters have been specified by your caller. If not, writes an error message and quits.
  2. Invokes the makePolygon function on the first parameter.
  3. Prints the resulting polygon information.
  4. Converts the second and third arguments to floating point values.
  5. Computes the x and y coordinates of the lower left corner of the bounding box and the upper right corner of the bounding box.
  6. Prints a message that tells the user what the lower left and upper right corners of the bounding box are.
  7. Checks to see if the (x,y) coordinate specified as the second and third parameters are inside the bounding box of the polygon.
  8. Prints a message to your caller that specifies the (x,y) coordinate of the user specified point, and tells whether that point is or is not contained in the bounding box of the polygon.

Your job today is to extend the main function to determine if a point that is inside the bounding box is also inside the polygon itself. In order to do that, you will need to do the following...

  1. Loop through the verteces of the polygon, looking for the two places where the vertical red line intersects the boundary of the polygon. In order to find these coordinates, you will have to do the following:
    1. Check to see if the query X matches this vertex X. If so, the vertex Y coordinate for this vertex is one of the intersection points.
    2. If not, use this vertex X as the "from" point of a line segment, and figure out what vertex will be the "to" point for the line segment. Then check to see if the query X is between the from and to X's. If not, the red vertical line does not cross this segment. If so, then the red vertical line does cross this segment, and you need to find the y coordinate of the intersection point. Do this by using the interpolation formula described above.
  2. Once you have the two y coordinates of the intersection of the vertical red line with the boundary of the polygon, you just need to check to see if the query Y coordinate is between the two intersection y coordinates. If so, the point is inside the perimeter of the polygon, and you should print a message to say so. If not, the point is outside the polygon itself, and your message should tell the user the point is outside the polygon.

Hints

Here are some hints that will help you write this code...

  1. Don't even bother to check to see if the point is inside the polygon if the point is outside the bounding box. If the point is outside the bounding box, it CAN'T be inside the polygon.
  2. Keep the index of the "to" coordinate for a line segment in its own variable, like int to_i Then you can have code like:
        if (i==verteces(p)-1) to_i=0;
          else to_i=i+1;
      
  3. Keep track of how many intersections you have found so far. When the number of intersections reaches 2, then you can check to see if the point is inside the polygon or not.
  4. If you downloaded the Professor's solution, he has already coded a function for you called interpolate which implements the interpolation formula described above.

Good luck and happy coding!

Lab Report

Download and edit the following file: lab5_report.txt. Then submit your editted file on Blackboard in the Lab_05 report area.