1 : /******************************************************************************
2 : * $Id: gdalrasterfpolygonenumerator.cpp 22502 2011-06-04 21:33:58Z rouault $
3 : *
4 : * Project: GDAL
5 : * Purpose: Version of Raster Polygon Enumerator using float buffers.
6 : * Author: Jorge Arevalo, jorge.arevalo@deimos-space.com. Most of the code
7 : * taken from GDALRasterFPolygonEnumerator, by Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2011, Jorge Arevalo
11 : * Copyright (c) 2008, Frank Warmerdam
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "gdal_alg_priv.h"
33 : #include "cpl_conv.h"
34 : #include <vector>
35 :
36 : CPL_CVSID("$Id: gdalrasterfpolygonenumerator.cpp 22502 2011-06-04 21:33:58Z rouault $");
37 :
38 : #ifdef OGR_ENABLED
39 : /************************************************************************/
40 : /* GDALRasterFPolygonEnumerator() */
41 : /************************************************************************/
42 :
43 0 : GDALRasterFPolygonEnumerator::GDALRasterFPolygonEnumerator(
44 : int nConnectedness )
45 :
46 : {
47 0 : panPolyIdMap = NULL;
48 0 : pafPolyValue = NULL;
49 0 : nNextPolygonId = 0;
50 0 : nPolyAlloc = 0;
51 0 : this->nConnectedness = nConnectedness;
52 0 : CPLAssert( nConnectedness == 4 || nConnectedness == 8 );
53 0 : }
54 :
55 : /************************************************************************/
56 : /* ~GDALRasterFPolygonEnumerator() */
57 : /************************************************************************/
58 :
59 0 : GDALRasterFPolygonEnumerator::~GDALRasterFPolygonEnumerator()
60 :
61 : {
62 0 : Clear();
63 0 : }
64 :
65 : /************************************************************************/
66 : /* Clear() */
67 : /************************************************************************/
68 :
69 0 : void GDALRasterFPolygonEnumerator::Clear()
70 :
71 : {
72 0 : CPLFree( panPolyIdMap );
73 0 : CPLFree( pafPolyValue );
74 :
75 0 : panPolyIdMap = NULL;
76 0 : pafPolyValue = NULL;
77 :
78 0 : nNextPolygonId = 0;
79 0 : nPolyAlloc = 0;
80 0 : }
81 :
82 : /************************************************************************/
83 : /* MergePolygon() */
84 : /* */
85 : /* Update the polygon map to indicate the merger of two polygons. */
86 : /************************************************************************/
87 :
88 0 : void GDALRasterFPolygonEnumerator::MergePolygon( int nSrcId, int nDstId )
89 :
90 : {
91 0 : while( panPolyIdMap[nDstId] != nDstId )
92 0 : nDstId = panPolyIdMap[nDstId];
93 :
94 0 : while( panPolyIdMap[nSrcId] != nSrcId )
95 0 : nSrcId = panPolyIdMap[nSrcId];
96 :
97 0 : if( nSrcId == nDstId )
98 0 : return;
99 :
100 0 : panPolyIdMap[nSrcId] = nDstId;
101 : }
102 :
103 : /************************************************************************/
104 : /* NewPolygon() */
105 : /* */
106 : /* Allocate a new polygon id, and reallocate the polygon maps */
107 : /* if needed. */
108 : /************************************************************************/
109 :
110 0 : int GDALRasterFPolygonEnumerator::NewPolygon( float fValue )
111 :
112 : {
113 0 : int nPolyId = nNextPolygonId;
114 :
115 0 : if( nNextPolygonId >= nPolyAlloc )
116 : {
117 0 : nPolyAlloc = nPolyAlloc * 2 + 20;
118 0 : panPolyIdMap = (GInt32 *) CPLRealloc(panPolyIdMap,nPolyAlloc*4);
119 0 : pafPolyValue = (float *) CPLRealloc(pafPolyValue,nPolyAlloc*4);
120 : }
121 :
122 0 : nNextPolygonId++;
123 :
124 0 : panPolyIdMap[nPolyId] = nPolyId;
125 0 : pafPolyValue[nPolyId] = fValue;
126 :
127 0 : return nPolyId;
128 : }
129 :
130 : /************************************************************************/
131 : /* CompleteMerges() */
132 : /* */
133 : /* Make a pass through the maps, ensuring every polygon id */
134 : /* points to the final id it should use, not an intermediate */
135 : /* value. */
136 : /************************************************************************/
137 :
138 0 : void GDALRasterFPolygonEnumerator::CompleteMerges()
139 :
140 : {
141 : int iPoly;
142 0 : int nFinalPolyCount = 0;
143 :
144 0 : for( iPoly = 0; iPoly < nNextPolygonId; iPoly++ )
145 : {
146 0 : while( panPolyIdMap[iPoly]
147 0 : != panPolyIdMap[panPolyIdMap[iPoly]] )
148 0 : panPolyIdMap[iPoly] = panPolyIdMap[panPolyIdMap[iPoly]];
149 :
150 0 : if( panPolyIdMap[iPoly] == iPoly )
151 0 : nFinalPolyCount++;
152 : }
153 :
154 : CPLDebug( "GDALRasterFPolygonEnumerator",
155 : "Counted %d polygon fragments forming %d final polygons.",
156 0 : nNextPolygonId, nFinalPolyCount );
157 0 : }
158 :
159 : /************************************************************************/
160 : /* ProcessLine() */
161 : /* */
162 : /* Assign ids to polygons, one line at a time. */
163 : /************************************************************************/
164 :
165 0 : void GDALRasterFPolygonEnumerator::ProcessLine(
166 : float *pafLastLineVal, float *pafThisLineVal,
167 : GInt32 *panLastLineId, GInt32 *panThisLineId,
168 : int nXSize )
169 :
170 : {
171 : int i;
172 :
173 : /* -------------------------------------------------------------------- */
174 : /* Special case for the first line. */
175 : /* -------------------------------------------------------------------- */
176 0 : if( pafLastLineVal == NULL )
177 : {
178 0 : for( i=0; i < nXSize; i++ )
179 : {
180 0 : if( i == 0 || !GDALFloatEquals(pafThisLineVal[i], pafThisLineVal[i-1]) )
181 : {
182 0 : panThisLineId[i] = NewPolygon( pafThisLineVal[i] );
183 : }
184 : else
185 0 : panThisLineId[i] = panThisLineId[i-1];
186 : }
187 :
188 0 : return;
189 : }
190 :
191 : /* -------------------------------------------------------------------- */
192 : /* Process each pixel comparing to the previous pixel, and to */
193 : /* the last line. */
194 : /* -------------------------------------------------------------------- */
195 0 : for( i = 0; i < nXSize; i++ )
196 : {
197 0 : if( i > 0 && GDALFloatEquals(pafThisLineVal[i], pafThisLineVal[i-1]) )
198 : {
199 0 : panThisLineId[i] = panThisLineId[i-1];
200 :
201 0 : if( GDALFloatEquals(pafLastLineVal[i], pafThisLineVal[i])
202 0 : && (panPolyIdMap[panLastLineId[i]]
203 0 : != panPolyIdMap[panThisLineId[i]]) )
204 : {
205 0 : MergePolygon( panLastLineId[i], panThisLineId[i] );
206 : }
207 : }
208 0 : else if( GDALFloatEquals(pafLastLineVal[i], pafThisLineVal[i]) )
209 : {
210 0 : panThisLineId[i] = panLastLineId[i];
211 : }
212 0 : else if( i > 0 && nConnectedness == 8
213 : && GDALFloatEquals(pafLastLineVal[i-1], pafThisLineVal[i]) )
214 : {
215 0 : panThisLineId[i] = panLastLineId[i-1];
216 : }
217 0 : else if( i < nXSize-1 && nConnectedness == 8
218 : && GDALFloatEquals(pafLastLineVal[i+1], pafThisLineVal[i]) )
219 : {
220 0 : panThisLineId[i] = panLastLineId[i+1];
221 : }
222 : else
223 0 : panThisLineId[i] =
224 0 : NewPolygon( pafThisLineVal[i] );
225 : }
226 : }
227 : #endif
|