1- import rbush from "geojson-rbush" ;
2- import clone from "@turf/clone" ;
3- import overlap from "@turf/boolean-overlap" ;
4- import turfUnion from "@turf/union" ;
5- import lineIntersect from "@turf/line-intersect" ;
6- import { coordAll } from "@turf/meta" ;
1+ import { featureCollection , multiPolygon , isObject } from "@turf/helpers" ;
72import { collectionOf } from "@turf/invariant" ;
8- import { lineString , isObject } from "@turf/helpers" ;
9- import { closestGreaterNumber } from "./lib/get-closest" ;
3+ import { featureEach } from "@turf/meta" ;
4+ import flatten from "@turf/flatten" ;
5+ import polygonClipping from "polygon-clipping" ;
106
117/**
128 * Dissolves a FeatureCollection of {@link polygon} features, filtered by an optional property name:value.
@@ -15,7 +11,7 @@ import { closestGreaterNumber } from "./lib/get-closest";
1511 * @name dissolve
1612 * @param {FeatureCollection<Polygon> } featureCollection input feature collection to be dissolved
1713 * @param {Object } [options={}] Optional parameters
18- * @param {string } [options.propertyName] features with equals 'propertyName' in `properties` will be merged
14+ * @param {string } [options.propertyName] features with the same `propertyName` value will be dissolved.
1915 * @returns {FeatureCollection<Polygon> } a FeatureCollection containing the dissolved polygons
2016 * @example
2117 * var features = turf.featureCollection([
@@ -29,118 +25,57 @@ import { closestGreaterNumber } from "./lib/get-closest";
2925 * //addToMap
3026 * var addToMap = [features, dissolved]
3127 */
32- function dissolve ( featureCollection , options ) {
28+ function dissolve ( fc , options ) {
3329 // Optional parameters
3430 options = options || { } ;
3531 if ( ! isObject ( options ) ) throw new Error ( "options is invalid" ) ;
3632 var propertyName = options . propertyName ;
3733
3834 // Input validation
39- collectionOf ( featureCollection , "Polygon" , "dissolve" ) ;
35+ collectionOf ( fc , "Polygon" , "dissolve" ) ;
4036
4137 // Main
42- var fc = clone ( featureCollection ) ;
43- var features = fc . features ;
44-
45- var originalIndexOfItemsRemoved = [ ] ;
46-
47- features . forEach ( function ( f , i ) {
48- f . properties . origIndexPosition = i ;
49- } ) ;
50- var tree = rbush ( ) ;
51- tree . load ( fc ) ;
52-
53- for ( var i in features ) {
54- var polygon = features [ i ] ;
55-
56- var featureChanged = false ;
57-
58- tree . search ( polygon ) . features . forEach ( function ( potentialMatchingFeature ) {
59- polygon = features [ i ] ;
60-
61- var matchFeaturePosition =
62- potentialMatchingFeature . properties . origIndexPosition ;
63-
38+ var outFeatures = [ ] ;
39+ if ( ! options . propertyName ) {
40+ return flatten (
41+ multiPolygon (
42+ polygonClipping . union . apply (
43+ null ,
44+ fc . features . map ( function ( f ) {
45+ return f . geometry . coordinates ;
46+ } )
47+ )
48+ )
49+ ) ;
50+ } else {
51+ var uniquePropertyVals = { } ;
52+ featureEach ( fc , function ( feature ) {
6453 if (
65- originalIndexOfItemsRemoved . length > 0 &&
66- matchFeaturePosition !== 0
54+ ! Object . prototype . hasOwnProperty . call (
55+ uniquePropertyVals ,
56+ feature . properties [ propertyName ]
57+ )
6758 ) {
68- if (
69- matchFeaturePosition >
70- originalIndexOfItemsRemoved [ originalIndexOfItemsRemoved . length - 1 ]
71- ) {
72- matchFeaturePosition =
73- matchFeaturePosition - originalIndexOfItemsRemoved . length ;
74- } else {
75- var closestNumber = closestGreaterNumber (
76- matchFeaturePosition ,
77- originalIndexOfItemsRemoved
78- ) ;
79- if ( closestNumber !== 0 ) {
80- matchFeaturePosition = matchFeaturePosition - closestNumber ;
81- }
82- }
59+ uniquePropertyVals [ feature . properties [ propertyName ] ] = [ ] ;
8360 }
84-
85- if ( matchFeaturePosition === + i ) return ;
86-
87- var matchFeature = features [ matchFeaturePosition ] ;
88- if ( ! matchFeature || ! polygon ) return ;
89-
90- if (
91- propertyName !== undefined &&
92- matchFeature . properties [ propertyName ] !==
93- polygon . properties [ propertyName ]
94- )
95- return ;
96-
97- if (
98- ! overlap ( polygon , matchFeature ) ||
99- ! ringsIntersect ( polygon , matchFeature )
100- )
101- return ;
102-
103- features [ i ] = turfUnion ( polygon , matchFeature ) ;
104-
105- originalIndexOfItemsRemoved . push (
106- potentialMatchingFeature . properties . origIndexPosition
107- ) ;
108- originalIndexOfItemsRemoved . sort ( function ( a , b ) {
109- return a - b ;
110- } ) ;
111-
112- tree . remove ( potentialMatchingFeature ) ;
113- features . splice ( matchFeaturePosition , 1 ) ;
114- polygon . properties . origIndexPosition = i ;
115- tree . remove ( polygon , function ( a , b ) {
116- return (
117- a . properties . origIndexPosition === b . properties . origIndexPosition
118- ) ;
119- } ) ;
120- featureChanged = true ;
61+ uniquePropertyVals [ feature . properties [ propertyName ] ] . push ( feature ) ;
12162 } ) ;
122-
123- if ( featureChanged ) {
124- if ( ! polygon ) continue ;
125- polygon . properties . origIndexPosition = i ;
126- tree . insert ( polygon ) ;
127- i -- ;
63+ var vals = Object . keys ( uniquePropertyVals ) ;
64+ for ( var i = 0 ; i < vals . length ; i ++ ) {
65+ var mp = multiPolygon (
66+ polygonClipping . union . apply (
67+ null ,
68+ uniquePropertyVals [ vals [ i ] ] . map ( function ( f ) {
69+ return f . geometry . coordinates ;
70+ } )
71+ )
72+ ) ;
73+ mp . properties [ propertyName ] = vals [ i ] ;
74+ outFeatures . push ( mp ) ;
12875 }
12976 }
13077
131- features . forEach ( function ( f ) {
132- delete f . properties . origIndexPosition ;
133- delete f . bbox ;
134- } ) ;
135-
136- return fc ;
137- }
138-
139- function ringsIntersect ( poly1 , poly2 ) {
140- var line1 = lineString ( coordAll ( poly1 ) ) ;
141- var line2 = lineString ( coordAll ( poly2 ) ) ;
142- var points = lineIntersect ( line1 , line2 ) . features ;
143- return points . length > 0 ;
78+ return flatten ( featureCollection ( outFeatures ) ) ;
14479}
14580
14681export default dissolve ;
0 commit comments