PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ SHPRewindObject()

int SHPAPI_CALL SHPRewindObject ( SHPHandle  hSHP,
SHPObject psObject 
)

Definition at line 2213 of file shpopen.c.

2215{
2216 int iOpRing, bAltered = 0;
2217
2218/* -------------------------------------------------------------------- */
2219/* Do nothing if this is not a polygon object. */
2220/* -------------------------------------------------------------------- */
2221 if( psObject->nSHPType != SHPT_POLYGON
2222 && psObject->nSHPType != SHPT_POLYGONZ
2223 && psObject->nSHPType != SHPT_POLYGONM )
2224 return 0;
2225
2226 if( psObject->nVertices == 0 || psObject->nParts == 0 )
2227 return 0;
2228
2229/* -------------------------------------------------------------------- */
2230/* Process each of the rings. */
2231/* -------------------------------------------------------------------- */
2232 for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
2233 {
2234 int bInner, iVert, nVertCount, nVertStart, iCheckRing;
2235 double dfSum, dfTestX, dfTestY;
2236
2237/* -------------------------------------------------------------------- */
2238/* Determine if this ring is an inner ring or an outer ring */
2239/* relative to all the other rings. For now we assume the */
2240/* first ring is outer and all others are inner, but eventually */
2241/* we need to fix this to handle multiple island polygons and */
2242/* unordered sets of rings. */
2243/* */
2244/* -------------------------------------------------------------------- */
2245
2246 /* Use point in the middle of segment to avoid testing
2247 * common points of rings.
2248 */
2249 dfTestX = ( psObject->padfX[psObject->panPartStart[iOpRing]]
2250 + psObject->padfX[psObject->panPartStart[iOpRing] + 1] ) / 2;
2251 dfTestY = ( psObject->padfY[psObject->panPartStart[iOpRing]]
2252 + psObject->padfY[psObject->panPartStart[iOpRing] + 1] ) / 2;
2253
2254 bInner = FALSE;
2255 for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
2256 {
2257 int iEdge;
2258
2259 if( iCheckRing == iOpRing )
2260 continue;
2261
2262 nVertStart = psObject->panPartStart[iCheckRing];
2263
2264 if( iCheckRing == psObject->nParts-1 )
2265 nVertCount = psObject->nVertices
2266 - psObject->panPartStart[iCheckRing];
2267 else
2268 nVertCount = psObject->panPartStart[iCheckRing+1]
2269 - psObject->panPartStart[iCheckRing];
2270
2271 for( iEdge = 0; iEdge < nVertCount; iEdge++ )
2272 {
2273 int iNext;
2274
2275 if( iEdge < nVertCount-1 )
2276 iNext = iEdge+1;
2277 else
2278 iNext = 0;
2279
2280 /* Rule #1:
2281 * Test whether the edge 'straddles' the horizontal ray from the test point (dfTestY,dfTestY)
2282 * The rule #1 also excludes edges collinear with the ray.
2283 */
2284 if ( ( psObject->padfY[iEdge+nVertStart] < dfTestY
2285 && dfTestY <= psObject->padfY[iNext+nVertStart] )
2286 || ( psObject->padfY[iNext+nVertStart] < dfTestY
2287 && dfTestY <= psObject->padfY[iEdge+nVertStart] ) )
2288 {
2289 /* Rule #2:
2290 * Test if edge-ray intersection is on the right from the test point (dfTestY,dfTestY)
2291 */
2292 double const intersect =
2293 ( psObject->padfX[iEdge+nVertStart]
2294 + ( dfTestY - psObject->padfY[iEdge+nVertStart] )
2295 / ( psObject->padfY[iNext+nVertStart] - psObject->padfY[iEdge+nVertStart] )
2296 * ( psObject->padfX[iNext+nVertStart] - psObject->padfX[iEdge+nVertStart] ) );
2297
2298 if (intersect < dfTestX)
2299 {
2300 bInner = !bInner;
2301 }
2302 }
2303 }
2304 } /* for iCheckRing */
2305
2306/* -------------------------------------------------------------------- */
2307/* Determine the current order of this ring so we will know if */
2308/* it has to be reversed. */
2309/* -------------------------------------------------------------------- */
2310 nVertStart = psObject->panPartStart[iOpRing];
2311
2312 if( iOpRing == psObject->nParts-1 )
2313 nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing];
2314 else
2315 nVertCount = psObject->panPartStart[iOpRing+1]
2316 - psObject->panPartStart[iOpRing];
2317
2318 if (nVertCount < 2)
2319 continue;
2320
2321 dfSum = psObject->padfX[nVertStart] * (psObject->padfY[nVertStart+1] - psObject->padfY[nVertStart+nVertCount-1]);
2322 for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
2323 {
2324 dfSum += psObject->padfX[iVert] * (psObject->padfY[iVert+1] - psObject->padfY[iVert-1]);
2325 }
2326
2327 dfSum += psObject->padfX[iVert] * (psObject->padfY[nVertStart] - psObject->padfY[iVert-1]);
2328
2329/* -------------------------------------------------------------------- */
2330/* Reverse if necessary. */
2331/* -------------------------------------------------------------------- */
2332 if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
2333 {
2334 int i;
2335
2336 bAltered++;
2337 for( i = 0; i < nVertCount/2; i++ )
2338 {
2339 double dfSaved;
2340
2341 /* Swap X */
2342 dfSaved = psObject->padfX[nVertStart+i];
2343 psObject->padfX[nVertStart+i] =
2344 psObject->padfX[nVertStart+nVertCount-i-1];
2345 psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
2346
2347 /* Swap Y */
2348 dfSaved = psObject->padfY[nVertStart+i];
2349 psObject->padfY[nVertStart+i] =
2350 psObject->padfY[nVertStart+nVertCount-i-1];
2351 psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
2352
2353 /* Swap Z */
2354 if( psObject->padfZ )
2355 {
2356 dfSaved = psObject->padfZ[nVertStart+i];
2357 psObject->padfZ[nVertStart+i] =
2358 psObject->padfZ[nVertStart+nVertCount-i-1];
2359 psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
2360 }
2361
2362 /* Swap M */
2363 if( psObject->padfM )
2364 {
2365 dfSaved = psObject->padfM[nVertStart+i];
2366 psObject->padfM[nVertStart+i] =
2367 psObject->padfM[nVertStart+nVertCount-i-1];
2368 psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
2369 }
2370 }
2371 }
2372 }
2373
2374 return bAltered;
2375}
#define SHPT_POLYGONM
Definition shapefil.h:317
#define SHPT_POLYGON
Definition shapefil.h:309
#define SHPT_POLYGONZ
Definition shapefil.h:313
#define FALSE
Definition shpopen.c:277
int * panPartStart
Definition shapefil.h:345
int nSHPType
Definition shapefil.h:340
int nVertices
Definition shapefil.h:348
double * padfZ
Definition shapefil.h:351
double * padfX
Definition shapefil.h:349
int nParts
Definition shapefil.h:344
double * padfM
Definition shapefil.h:352
double * padfY
Definition shapefil.h:350

References FALSE, SHPObject::nParts, SHPObject::nSHPType, SHPObject::nVertices, SHPObject::padfM, SHPObject::padfX, SHPObject::padfY, SHPObject::padfZ, SHPObject::panPartStart, SHPT_POLYGON, SHPT_POLYGONM, and SHPT_POLYGONZ.