PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ SHPRewindObject()

int SHPAPI_CALL SHPRewindObject ( SHPHandle  hSHP,
SHPObject psObject 
)

Definition at line 2213 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.

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 }
int * panPartStart
Definition: shapefil.h:345
#define SHPT_POLYGONM
Definition: shapefil.h:317
int nVertices
Definition: shapefil.h:348
double * padfX
Definition: shapefil.h:349
#define SHPT_POLYGON
Definition: shapefil.h:309
double * padfY
Definition: shapefil.h:350
#define FALSE
Definition: shpopen.c:277
int nParts
Definition: shapefil.h:344
#define SHPT_POLYGONZ
Definition: shapefil.h:313
double * padfZ
Definition: shapefil.h:351
int nSHPType
Definition: shapefil.h:340
double * padfM
Definition: shapefil.h:352