/*
 PolygonPartition::sweep
 Determines if two polygons are neighbors. The host is assumed to be
 partitioned.
 Uses two criteria to establish neighborhood:
 is_queen == true then: common point, else: common boundary
 */
int PolygonPartition::sweep(PolygonPartition & guest, bool is_queen,
                            double precision_threshold)
{
	int       host, dot, cly, cell;
	double    yStart= GetMinY(), yStop= GetMaxY();
	Shapefile::Point* pt;
	guest.MakeSmallPartition(pX.Cells(), GetMinX(), GetMaxX());
	for (cell= 0; cell < pX.Cells(); ++cell) {
		for (host= pX.first(cell); host != GdaConst::EMPTY; host= pX.tail(host))
            pY.include(host);
		for (dot=guest.pX.first(cell); dot != GdaConst::EMPTY; dot=guest.pX.tail(dot))
        {
			pt= guest.GetPoint(dot);
			cly= pY.inTheRange(pt->y - yStart);
			if (cly != -1) {
				for (host= pY.first(cly); host != GdaConst::EMPTY;
					 host= pY.tail(host))
                {
					if (pt->equals( GetPoint(host), precision_threshold) )
                    {
						if (is_queen || edge(guest, host, dot, precision_threshold)) {
							pY.cleanup(pX, cell);
							return 1;  
						}
					}
				}
			}
		}
		pY.cleanup(pX, cell);
	}
	return 0;
	
}
Beispiel #2
0
GalElement* shp2gal(Shapefile::Main& main, int criteria, bool save,
                    double precision_threshold)
{
	using namespace Shapefile;
	
	GalElement * full;
	//ReadOffsets(fname);
	//ReadBoxes(fname);
	gRecords = main.records.size();
	double shp_min_x = (double)main.header.bbox_x_min;
	double shp_max_x = (double)main.header.bbox_x_max;
	double shp_min_y = (double)main.header.bbox_y_min;
	double shp_max_y = (double)main.header.bbox_y_max;
	double shp_x_len = shp_max_x - shp_min_x;
	double shp_y_len = shp_max_y - shp_min_y;
	
	long gx, gy, cnt, total=0;
	gx= gRecords / 8 + 2;
	
	gMinX.alloc(gRecords, gx, shp_x_len );
	gMaxX.alloc(gRecords, gx, shp_x_len );
	
	
	
	for (cnt= 0; cnt < gRecords; ++cnt) {
		PolygonContents* ply = dynamic_cast<PolygonContents*> (
											main.records[cnt].contents_p);
		
		gMinX.include( cnt, ply->box[0] - shp_min_x );
		gMaxX.include( cnt, ply->box[2] - shp_min_x );
	}
	
	gy= (int)(sqrt((long double)gRecords) + 2);
	do {
		gY= new PartitionM(gRecords, gy, shp_y_len );
		for (cnt= 0; cnt < gRecords; ++cnt) {
			PolygonContents* ply = dynamic_cast<PolygonContents*> (
											main.records[cnt].contents_p);
			gY->initIx( cnt, ply->box[1] - shp_min_y, ply->box[3] - shp_min_y );
		}
		total= gY->Sum();
		if (total > gRecords * 8) {
			delete gY;
			gy = gy/2 + 1;
			total= 0;
		}
	} while ( total == 0);
	
	GalElement * gl= MakeContiguity(main, criteria, precision_threshold);
    
	if (gY) delete gY; gY = 0;
	if (gOffset) delete [] gOffset; gOffset = 0;
	if (gBox) delete [] gBox; gBox = 0;
	
	full = MakeFull(gl);
	if (gl) delete [] gl; gl = 0;
	return full;
}
/*
 PolygonPartition
 */
void PolygonPartition::MakeSmallPartition(const int mX, const double Start,
										  const double Stop)
{
	pX.alloc(NumPoints, mX, Stop-Start);
	for (int cnt= 0; cnt < NumPoints; ++cnt) {
		Shapefile::Point* pt= GetPoint(cnt);
		if (pt->x >= Start && pt->x <= Stop) pX.include(cnt, pt->x - Start);
	}
	MakeNeighbors();
}
/*
 PolygonPartition
 */
int PolygonPartition::MakePartition(int mX, int mY)  {
	if (mX == 0) mX = NumPoints/4 + 2;
	if (mY == 0) mY = (int)(sqrt((long double)NumPoints) + 2);
	pX.alloc(NumPoints, mX, GetMaxX() - GetMinX());// bBox._max().x - bBox._min().x);
	pY.alloc(NumPoints, mY, GetMaxY() - GetMinY());//bBox._max().y - bBox._min().y);
	double xStart= GetMinX(), yStart= GetMinY();
	for (int cnt= 0; cnt < NumPoints; ++cnt)  {
		pX.include(cnt, GetPoint(cnt)->x - xStart);
		pY.initIx(cnt, GetPoint(cnt)->y - yStart);
	};
	MakeNeighbors();
	return 0;	
}
Beispiel #5
0
GalElement* MakeContiguity(Shapefile::Main& main, const int crit,
                           double precision_threshold=0.0)
{
	using namespace Shapefile;
	int curr;
	GalElement * gl= new GalElement [ gRecords ];
	
	if (!gl) return NULL;
	GeoDaSet   Neighbors(gRecords), Related(gRecords);
	//  cout << "total steps= " << gMinX.Cells() << endl;
	for (int step= 0; step < gMinX.Cells(); ++step) {
		// include all elements from xmin[step]
		for (curr= gMinX.first(step); curr != GdaConst::EMPTY;
			 curr= gMinX.tail(curr)) gY->include(curr);
		
		// test each element in xmax[step]
		for (curr= gMaxX.first(step); curr != GdaConst::EMPTY;
			 curr= gMaxX.tail(curr))  {
			PolygonContents* ply = dynamic_cast<PolygonContents*> (
												main.records[curr].contents_p);
			PolygonPartition testPoly(ply);
			testPoly.MakePartition();
			
			// form a list of neighbors
			for (int cell=gY->lowest(curr); cell <= gY->upmost(curr); ++cell) {
				int potential = gY->first( cell );
				while (potential != GdaConst::EMPTY) {
					if (potential != curr) Neighbors.Push( potential );
					potential = gY->tail(potential, cell);
				}
			}
			
			// test each potential neighbor
			for (int nbr = Neighbors.Pop(); nbr != GdaConst::EMPTY;
				 nbr = Neighbors.Pop()) {
				PolygonContents* nbr_ply = dynamic_cast<PolygonContents*> (
												main.records[nbr].contents_p);
				if (ply->intersect(nbr_ply)) {
					
					PolygonPartition nbrPoly(nbr_ply);
					//shp.seekg(gOffset[nbr]+12, ios::beg);
					//nbrPoly.ReadShape(shp);
					
					if (curr == 0 && nbr == 0) {
						
					}
					
					// run sweep with testPoly as a host and nbrPoly as a guest
					int related = testPoly.sweep(nbrPoly, crit,
                                                 precision_threshold);
					if (related) Related.Push(nbr);
				}
			}
			
			if (Related.Size() && gl[curr].alloc(Related.Size())) {
				while (Related.Size()) gl[curr].Push(Related.Pop());
			}
			
			gY->remove(curr);       // remove from the partition
		}
	}
	
	return gl;
}
	void cleanup(const BasePartition &p, const int cl)  {
		for (int cnt= p.first(cl); cnt != GdaConst::EMPTY; cnt= p.tail(cnt))
			remove(cnt);
	}