/* 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; }
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; }
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); }