PostGIS  2.1.10dev-r@@SVN_REVISION@@
int SHPAPI_CALL SHPRewindObject ( SHPHandle  hSHP,
SHPObject psObject 
)

Definition at line 2214 of file shpopen.c.

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.

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