41
41
#endif
42
42
43
43
/* custom attributes provided by this layer data source */
44
- #define MSCLUSTER_NUMITEMS 2
44
+ #define MSCLUSTER_NUMITEMS 3
45
45
#define MSCLUSTER_FEATURECOUNT "Cluster:FeatureCount"
46
46
#define MSCLUSTER_FEATURECOUNTINDEX -100
47
47
#define MSCLUSTER_GROUP "Cluster:Group"
48
48
#define MSCLUSTER_GROUPINDEX -101
49
+ #define MSCLUSTER_BASEFID "Cluster:BaseFID"
50
+ #define MSCLUSTER_BASEFIDINDEX -102
49
51
50
52
typedef struct cluster_tree_node clusterTreeNode ;
51
53
typedef struct cluster_info clusterInfo ;
@@ -115,6 +117,10 @@ struct cluster_layer_info {
115
117
clusterInfo * current ;
116
118
/* check whether all shapes should be returned behind a cluster */
117
119
int get_all_shapes ;
120
+ /* check whether the location of the shapes should be preserved (no averaging) */
121
+ int keep_locations ;
122
+ /* the maxdistance and the buffer parameters are specified in map units (scale independent clustering) */
123
+ int use_map_units ;
118
124
double rank ;
119
125
/* root node of the quad tree */
120
126
clusterTreeNode * root ;
@@ -496,6 +502,11 @@ static void InitShapeAttributes(layerObj* layer, clusterInfo* base)
496
502
base -> shape .values [i ] = msStrdup (base -> group );
497
503
else
498
504
base -> shape .values [i ] = msStrdup ("" );
505
+ } else if (itemindexes [i ] == MSCLUSTER_BASEFIDINDEX ) {
506
+ if (base -> shape .values [i ])
507
+ msFree (base -> shape .values [i ]);
508
+
509
+ base -> shape .values [i ] = msIntToString (base -> shape .index );
499
510
} else if (EQUALN (layer -> items [i ], "Count:" , 6 )) {
500
511
if (base -> shape .values [i ])
501
512
msFree (base -> shape .values [i ]);
@@ -522,6 +533,12 @@ static void UpdateShapeAttributes(layerObj* layer, clusterInfo* base, clusterInf
522
533
if (current -> shape .numvalues <= i )
523
534
break ;
524
535
536
+ /* setting the base feature index for each cluster member */
537
+ if (itemindexes [i ] == MSCLUSTER_BASEFIDINDEX ) {
538
+ msFree (current -> shape .values [i ]);
539
+ current -> shape .values [i ] = msIntToString (base -> shape .index );
540
+ }
541
+
525
542
if (current -> shape .values [i ]) {
526
543
if (EQUALN (layer -> items [i ], "Min:" , 4 )) {
527
544
if (strcasecmp (base -> shape .values [i ], current -> shape .values [i ]) > 0 ) {
@@ -567,6 +584,8 @@ static int BuildFeatureAttributes(layerObj* layer, msClusterLayerInfo* layerinfo
567
584
values [i ] = NULL ; /* not yet assigned */
568
585
} else if (itemindexes [i ] == MSCLUSTER_GROUPINDEX ) {
569
586
values [i ] = NULL ; /* not yet assigned */
587
+ } else if (itemindexes [i ] == MSCLUSTER_BASEFIDINDEX ) {
588
+ values [i ] = NULL ; /* not yet assigned */
570
589
} else if (shape -> values [itemindexes [i ]])
571
590
values [i ] = msStrdup (shape -> values [itemindexes [i ]]);
572
591
else
@@ -779,8 +798,11 @@ int selectClusterShape(layerObj* layer, long shapeindex)
779
798
780
799
current -> next = current -> siblings ;
781
800
layerinfo -> current = current ;
782
- current -> shape .line [0 ].point [0 ].x = current -> shape .bounds .minx = current -> shape .bounds .maxx = current -> avgx ;
783
- current -> shape .line [0 ].point [0 ].y = current -> shape .bounds .miny = current -> shape .bounds .maxy = current -> avgy ;
801
+
802
+ if (layerinfo -> keep_locations == MS_FALSE ) {
803
+ current -> shape .line [0 ].point [0 ].x = current -> shape .bounds .minx = current -> shape .bounds .maxx = current -> avgx ;
804
+ current -> shape .line [0 ].point [0 ].y = current -> shape .bounds .miny = current -> shape .bounds .maxy = current -> avgy ;
805
+ }
784
806
785
807
return MS_SUCCESS ;
786
808
}
@@ -893,6 +915,19 @@ int RebuildClusters(layerObj *layer, int isQuery)
893
915
else
894
916
layerinfo -> get_all_shapes = MS_FALSE ;
895
917
918
+ /* check whether the location of the shapes should be preserved (no averaging) */
919
+ if (msLayerGetProcessingKey (layer , "CLUSTER_KEEP_LOCATIONS" ) != NULL )
920
+ layerinfo -> keep_locations = MS_TRUE ;
921
+ else
922
+ layerinfo -> keep_locations = MS_FALSE ;
923
+
924
+ /* check whether the maxdistance and the buffer parameters
925
+ are specified in map units (scale independent clustering) */
926
+ if (msLayerGetProcessingKey (layer , "CLUSTER_USE_MAP_UNITS" ) != NULL )
927
+ layerinfo -> use_map_units = MS_TRUE ;
928
+ else
929
+ layerinfo -> use_map_units = MS_FALSE ;
930
+
896
931
/* identify the current extent */
897
932
if (layer -> transform == MS_TRUE )
898
933
searchrect = map -> extent ;
@@ -931,16 +966,25 @@ int RebuildClusters(layerObj *layer, int isQuery)
931
966
/* trying to find a reasonable quadtree depth */
932
967
depth = 0 ;
933
968
distance = layer -> cluster .maxdistance ;
934
- while ((distance < map -> width || distance < map -> height ) && depth <= TREE_MAX_DEPTH ) {
935
- distance *= 2 ;
936
- ++ depth ;
969
+ if (layerinfo -> use_map_units == MS_TRUE ) {
970
+ while ((distance < (searchrect .maxx - searchrect .minx ) || distance < (searchrect .maxy - searchrect .miny )) && depth <= TREE_MAX_DEPTH ) {
971
+ distance *= 2 ;
972
+ ++ depth ;
973
+ }
974
+ cellSizeX = 1 ;
975
+ cellSizeY = 1 ;
976
+ }
977
+ else {
978
+ while ((distance < map -> width || distance < map -> height ) && depth <= TREE_MAX_DEPTH ) {
979
+ distance *= 2 ;
980
+ ++ depth ;
981
+ }
982
+ cellSizeX = MS_CELLSIZE (searchrect .minx , searchrect .maxx , map -> width );
983
+ cellSizeY = MS_CELLSIZE (searchrect .miny , searchrect .maxy , map -> height );
937
984
}
938
985
939
986
layerinfo -> depth = depth ;
940
987
941
- cellSizeX = MS_CELLSIZE (searchrect .minx , searchrect .maxx , map -> width );
942
- cellSizeY = MS_CELLSIZE (searchrect .miny , searchrect .maxy , map -> height );
943
-
944
988
maxDistanceX = layer -> cluster .maxdistance * cellSizeX ;
945
989
maxDistanceY = layer -> cluster .maxdistance * cellSizeY ;
946
990
@@ -1213,6 +1257,8 @@ int msClusterLayerInitItemInfo(layerObj *layer)
1213
1257
itemindexes [i ] = MSCLUSTER_FEATURECOUNTINDEX ;
1214
1258
else if (EQUAL (layer -> items [i ], MSCLUSTER_GROUP ))
1215
1259
itemindexes [i ] = MSCLUSTER_GROUPINDEX ;
1260
+ else if (EQUAL (layer -> items [i ], MSCLUSTER_BASEFID ))
1261
+ itemindexes [i ] = MSCLUSTER_BASEFIDINDEX ;
1216
1262
else
1217
1263
itemindexes [i ] = numitems ++ ;
1218
1264
}
@@ -1266,8 +1312,10 @@ static int prepareShape(layerObj* layer, msClusterLayerInfo* layerinfo, clusterI
1266
1312
}
1267
1313
1268
1314
/* update the positions of the cluster shape */
1269
- shape -> line [0 ].point [0 ].x = shape -> bounds .minx = shape -> bounds .maxx = current -> avgx ;
1270
- shape -> line [0 ].point [0 ].y = shape -> bounds .miny = shape -> bounds .maxy = current -> avgy ;
1315
+ if (layerinfo -> keep_locations == MS_FALSE ) {
1316
+ shape -> line [0 ].point [0 ].x = shape -> bounds .minx = shape -> bounds .maxx = current -> avgx ;
1317
+ shape -> line [0 ].point [0 ].y = shape -> bounds .miny = shape -> bounds .maxy = current -> avgy ;
1318
+ }
1271
1319
1272
1320
return MS_SUCCESS ;
1273
1321
}
@@ -1330,6 +1378,7 @@ int msClusterLayerGetItems(layerObj *layer)
1330
1378
layer -> items = msSmallMalloc (sizeof (char * ) * (layer -> numitems ));
1331
1379
layer -> items [0 ] = msStrdup (MSCLUSTER_FEATURECOUNT );
1332
1380
layer -> items [1 ] = msStrdup (MSCLUSTER_GROUP );
1381
+ layer -> items [2 ] = msStrdup (MSCLUSTER_BASEFID );
1333
1382
1334
1383
return msClusterLayerInitItemInfo (layer );
1335
1384
}
0 commit comments