@@ -1190,8 +1190,10 @@ Base.@kwdef struct GMTConComp
11901190 proj4:: String = " "
11911191 wkt:: String = " "
11921192 epsg:: Int = 0
1193- bboxs:: Vector{GMTdataset{Float64,2}} = GMTdataset{Float64,2 }[] # The bounding boxes as datasets
1194- pixel_list:: Vector{Vector{Int32}} = Vector{Int32}[] # The list of pixel indices for each component
1193+ bbox:: Vector{GMTdataset{Float64,2}} = GMTdataset{Float64,2 }[] # The bounding boxes as datasets
1194+ pixel_list:: Vector{Vector{Int32}} = Vector{Int32}[] # The list of pixel indices for each component
1195+ centroid:: Matrix{Float64} = Matrix {Float64} (undef, 0 , 0 ) # The centroids of each component
1196+ area:: Vector{Float64} = Float64[] # The areas of each component
11951197end
11961198
11971199"""
@@ -1220,8 +1222,10 @@ A `GMTConComp` structure with the following fields:
12201222- `proj4`: Projection definition of the image used to find the components.
12211223- `wkt`: Well-known text definition of the image used to find the components.
12221224- `epsg`: EPSG code of the image used to find the components.
1223- - `bboxs`: The bounding boxes as a vector of GMTdataset.
1224- - `pixel_list`: A vevtor of vectors with the list of linear pixel indices for each component.
1225+ - `bbox`: The bounding boxes as a vector of GMTdataset.
1226+ - `pixel_list`: A vector of vectors with the list of linear pixel indices for each component.
1227+ - `centroid`: A vector of Float64 Tuples with the x,y coordinates of the centroids for each component.
1228+ - `area`: A vector of Float64 with the areas of each component. This area is approximated by the mean lat for geog images.
12251229"""
12261230bwconncomp (mat:: BitMatrix ; conn:: Int = 8 ) = bwconncomp (mat2img (collect (mat)); conn= conn)
12271231bwconncomp (mat:: Matrix{<:Bool} ; conn:: Int = 8 ) = bwconncomp (mat2img (mat); conn= conn)
@@ -1241,30 +1245,53 @@ function bwconncomp(I::GMTimage; conn::Int=8)
12411245 # ppix = unsafe_load(unsafe_load(pixa).pix, 1)
12421246 # return pix2img(Sppix(ppix))
12431247
1244- boxa = unsafe_load (pboxa)
1245- D = Vector {GMTdataset{Float64,2}} (undef, boxa. n)
1248+ is_geog = isgeog (I)
1249+ cellsize = I. inc[1 ] * I. inc[2 ]
1250+ boxa = unsafe_load (pboxa)
1251+ D = Vector {GMTdataset{Float64,2}} (undef, boxa. n)
1252+ centroid = Matrix {Float64} (undef, boxa. n, 2 )
1253+ area = Vector {Float64} (undef, boxa. n)
12461254 pixel_list = [Int32[] for _ in 1 : boxa. n]
12471255 width, height = getsize (I)
1256+ is_col_maj = (I. layout[2 ] == ' C' )
1257+ is_top_down = (I. layout[1 ] == ' T' )
1258+
12481259 @inbounds for k = 1 : boxa. n
1249- b = unsafe_load (unsafe_load (boxa. box, k)) # A Box, x,y counting seem to be 0-based
1250- y2 = I. y[Int32 (width - b. y)]
1251- y1 = I. y[Int32 (width - b. y - b. h)]
1252- x1, x2 = I. x[b. x + I. registration], I. x[b. x + b. w + I. registration] # Still not very clear where/why +1's are needed
1253- D[k] = mat2ds ([x1 y1; x1 y2; x2 y2; x2 y1; x1 y1]) # The bounding box
1254- D[k]. bbox = [x1, x2, y1, y2] # (xmin, xmax, ymin, ymax)
1255- if (I. layout[2 ] == ' C' ) # Column major
1256- jj = (I. layout[1 ] == ' T' ) ? (b. y+ 1 : b. y+ b. h) : (height- b. y: - 1 : height - b. y - b. h + 1 )
1257- @inbounds for i = b. x+ 1 : b. x+ b. w, j = jj
1258- (I[j,i] != 0 ) && append! (pixel_list[k], (i- 1 ) * height + j)
1260+ b = unsafe_load (unsafe_load (boxa. box, k)) # A Box, x,y counting seem to be 0-based
1261+ y2 = I. y[Int32 (height - b. y) + 1 ]
1262+ y1 = I. y[Int32 (height - b. y - b. h) + 1 ]
1263+ x1, x2 = I. x[b. x + I. registration], I. x[b. x + b. w + I. registration]
1264+ D[k] = mat2ds ([x1 y1; x1 y2; x2 y2; x2 y1; x1 y1]) # The bounding box
1265+ D[k]. bbox = [x1, x2, y1, y2] # (xmin, xmax, ymin, ymax)
1266+ half_pix_x, half_pix_y = I. registration * I. inc[1 ]/ 2 , I. registration * I. inc[2 ]/ 2
1267+ im, jm = 0.0 , 0.0
1268+
1269+ if (is_col_maj) # Column major
1270+ jj = (is_top_down) ? (b. y+ 1 : b. y+ b. h) : (height- b. y: - 1 : height - b. y - b. h + 1 )
1271+ @inbounds for i in b. x+ 1 : b. x+ b. w # Xaxis
1272+ @inbounds for j in jj
1273+ (I[j,i] != 0 ) && (append! (pixel_list[k], (i- 1 ) * height + j); jm += j; im += i)
1274+ end
12591275 end
1260- else # Row major
1261- @inbounds for j = b. y+ 1 : b. y+ b. h, i = b. x+ 1 : b. x+ b. w # Oddly here we do not need to care about 'T' or 'B'
1262- (I[i,j] != 0 ) && append! (pixel_list[k], (j- 1 ) * width + i)
1276+ n_px = length (pixel_list[k])
1277+ t = (is_top_down) ? (I. range[4 ] - half_pix_y) - (jm / n_px - 1 )* I. inc[2 ] : (I. range[3 ] + half_pix_x) + (jm / n_px - 1 )* I. inc[2 ]
1278+ centroid[k,1 : 2 ] .= (I. range[1 ] + half_pix_x) + (im / n_px - 1 )* I. inc[1 ], t
1279+ else # Row major
1280+ @inbounds for j = b. y+ 1 : b. y+ b. h # Yaxis.
1281+ @inbounds for i = b. x+ 1 : b. x+ b. w
1282+ (I[i,j] != 0 ) && (append! (pixel_list[k], (j- 1 ) * width + i); im += i; jm += j)
1283+ end
12631284 end
1285+ n_px = length (pixel_list[k])
1286+ t = (is_top_down) ? (I. range[2 ] - half_pix_y) - (jm / n_px - 1 )* I. inc[1 ] : (I. range[1 ] + half_pix_y) + (jm / n_px - 1 )* I. inc[1 ]
1287+ centroid[k,1 : 2 ] .= (I. range[3 ] + half_pix_x) + (im / n_px - 1 )* I. inc[2 ], t
12641288 end
1289+ lat_fact = (is_geog) ? cosd (centroid[k][2 ]) : 1.0 # Big approximation for the geog case but exact solution is too complex here
1290+ area[k] = n_px * cellsize * lat_fact
12651291 end
12661292 set_dsBB! (D, true ) # Add the bounding box
1267- GMTConComp (conn, pcount[], size (I), I. range, I. inc, I. registration, I. x, I. y, I. layout, I. proj4, I. wkt, I. epsg, D, pixel_list)
1293+ GMTConComp (conn, pcount[], size (I), I. range, I. inc, I. registration, I. x, I. y, I. layout, I. proj4, I. wkt, I. epsg,
1294+ D, pixel_list, centroid, area)
12681295end
12691296
12701297function get_ppixI (I)
0 commit comments