FINAL PROJECT
DUE: Dec 18, 2001
The final project will be a class effort. We will divide the effort into 3 parts.
PART A: Constructing the search infrastructure for processing TIGER data into hierarchical LOD structures.
PART B: Constructing Search Structures, on both the client and server sides.
PART C: Constructing the Client/Server System.
We shall aim at working with 16 counties as the goal - these 16 counties will be the 5 boroughs of NYC, plus surrounding counties in New York and New Jersey. Parts and pieces of the necessary code are already embedded in our first 3 homeworks, so reuse them whenever possible. BUT I stree that it is important to stick to the specs and to the deadlines specified below. Any variation in these specs should be discussed with me.
But in what order do we merge counties? What we want is the merge tree for the 16 counties. In our TIGER resource page. there is a list of 435 counties from 14 states in North East USA, from Maine to Virginia. This list contains the adjacency graph of all the counties. We will take advantage of this information to construct our data structure. Since we only have 16 counties, we will construct the merge tree by hand.
We assume the merge tree is binary. At each node of the merge tree, we store the following information:
///////////////////////////////////////////////////////
// Merge Node class
///////////////////////////////////////////////////////
class MergeNode {
public:
int xmin, xmax; // bounding box
int ymin, ymax; // information
int sScale; // Level of Detail (LOD)
MergeNode leftChild, rightChild;
Outline oStruct; // outline layer (see below)
Network nStruct; // road layer (see below)
RangeTree rStruct; // range tree search structure
HashTable hStruct; // hash table
// CONSTRUCTORS:
MergeNode(TigerSubdiv & ts); // create a leaf node
MergeNode(MergeNode & mn1, MergeNode & mn2);
// create an internal node from two children
// METHODS:
void Dump(char * fname); // Write out to one or more files
} //class MergeNode
The Outline and Network classes are derived from of TigerSubdiv class (see below). The RangeTree will contain all the endpoints of TLines in these two classes.
How we do a window query at a MergeNode? Actually, each window query is accompanied by a ßScale" (screen scale value). There are two cases:
CASE 1: The sScale at the current MergeNode is greater than the sScale of the query. Then the window search is recursively sent to the children of the current MergeNode. We send it to a child only if the query window intersects the bounding box of the child.
CASE 2: In this case we directly search the current node. We first use the range tree to determine retrieve all points in the query window. Each point knows whether it belongs to the Outline or the Network structure. For each point in either structure, we can retrieve all the TLines that are incident on it. Each TLine has a unique ID. We try to insert these TLines into the hash table. If unsuccessful, it means that the client already has this information. Otherwise, this is sent to the client. Similarly, we retrieve all polygons in the Outline structure, try to insert them in the hash table. Again, only send if the insertion is successful.
This completes the duty on the server side. What happens at the client side? The client also has the merge tree, but does not need the hash table. Also, its Outline and Network and Range structures are initially empty. As vertices, edges and polygons are sent, we fill them into the structure.
We need to worry about main memory: it is assumed that each MergeNode data is stored in a set of files and they are read into main memory as needed. We need to do a little bit of simple paging.
///////////////////////////////////////////////////////
// Derived classes for Outline and Network
///////////////////////////////////////////////////////
class Outline : public Subdivision {
public:
int sScale; // screen scale
int childSubdiv[2]; // the child subdivision
}
class Network : public Subdivision {
//
// ...
}
We now need to implement methods to merge and simplify these two layers of data. We treat these two layers as INDEPENDENT of each in the merging and simplication process. Merging is basically simple: it is just the union of the lists of vertices, edges, etc. However, you need to remove duplicates at the boundary.
Simplification is based on some maximum error bounds denoted sScale which, as in hw2, means the ßcreen scale". Thus sScale = 87 means 87 meters per pixel. There are two steps: (1) First, we simplify TLines, using the the same Douglas Peucker algorithm as specified in hw2. (2) Next, we eliminate small polygons. The rule here is that for any polygon whose bounding box area is less than MIN_PIXEL_AREA pixels will be eliminated.
///////////////////////////////////////////////////////
// methods to reomve polygons
///////////////////////////////////////////////////////
void TigerSubdiv::checkPolygon(int polyID, int sScale)
// Check if polyID has area that is too small
// Remove it if so.
void TigerSubdiv::removePolygon(int sScale)
// Apply polyID if its area is too small
We assume that the server forks to serve each client and the messages between them are as follows:
The client will have four threads, each with its own input queue ("Q").