]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Geometry/MultiLineString.js
initial commit
[syp.git] / openlayers / lib / OpenLayers / Geometry / MultiLineString.js
1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2  * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3  * full text of the license. */
4
5 /**
6  * @requires OpenLayers/Geometry/Collection.js
7  * @requires OpenLayers/Geometry/LineString.js
8  */
9
10 /**
11  * Class: OpenLayers.Geometry.MultiLineString
12  * A MultiLineString is a geometry with multiple <OpenLayers.Geometry.LineString>
13  * components.
14  * 
15  * Inherits from:
16  *  - <OpenLayers.Geometry.Collection>
17  *  - <OpenLayers.Geometry> 
18  */
19 OpenLayers.Geometry.MultiLineString = OpenLayers.Class(
20   OpenLayers.Geometry.Collection, {
21
22     /**
23      * Property: componentTypes
24      * {Array(String)} An array of class names representing the types of
25      * components that the collection can include.  A null value means the
26      * component types are not restricted.
27      */
28     componentTypes: ["OpenLayers.Geometry.LineString"],
29
30     /**
31      * Constructor: OpenLayers.Geometry.MultiLineString
32      * Constructor for a MultiLineString Geometry.
33      *
34      * Parameters: 
35      * components - {Array(<OpenLayers.Geometry.LineString>)} 
36      *
37      */
38     initialize: function(components) {
39         OpenLayers.Geometry.Collection.prototype.initialize.apply(this, 
40                                                                   arguments);        
41     },
42     
43     /**
44      * Method: split
45      * Use this geometry (the source) to attempt to split a target geometry.
46      * 
47      * Parameters:
48      * target - {<OpenLayers.Geometry>} The target geometry.
49      * options - {Object} Properties of this object will be used to determine
50      *     how the split is conducted.
51      *
52      * Valid options:
53      * mutual - {Boolean} Split the source geometry in addition to the target
54      *     geometry.  Default is false.
55      * edge - {Boolean} Allow splitting when only edges intersect.  Default is
56      *     true.  If false, a vertex on the source must be within the tolerance
57      *     distance of the intersection to be considered a split.
58      * tolerance - {Number} If a non-null value is provided, intersections
59      *     within the tolerance distance of an existing vertex on the source
60      *     will be assumed to occur at the vertex.
61      * 
62      * Returns:
63      * {Array} A list of geometries (of this same type as the target) that
64      *     result from splitting the target with the source geometry.  The
65      *     source and target geometry will remain unmodified.  If no split
66      *     results, null will be returned.  If mutual is true and a split
67      *     results, return will be an array of two arrays - the first will be
68      *     all geometries that result from splitting the source geometry and
69      *     the second will be all geometries that result from splitting the
70      *     target geometry.
71      */
72     split: function(geometry, options) {
73         var results = null;
74         var mutual = options && options.mutual;
75         var splits, sourceLine, sourceLines, sourceSplit, targetSplit;
76         var sourceParts = [];
77         var targetParts = [geometry];
78         for(var i=0, len=this.components.length; i<len; ++i) {
79             sourceLine = this.components[i];
80             sourceSplit = false;
81             for(var j=0; j < targetParts.length; ++j) { 
82                 splits = sourceLine.split(targetParts[j], options);
83                 if(splits) {
84                     if(mutual) {
85                         sourceLines = splits[0];
86                         for(var k=0, klen=sourceLines.length; k<klen; ++k) {
87                             if(k===0 && sourceParts.length) {
88                                 sourceParts[sourceParts.length-1].addComponent(
89                                     sourceLines[k]
90                                 );
91                             } else {
92                                 sourceParts.push(
93                                     new OpenLayers.Geometry.MultiLineString([
94                                         sourceLines[k]
95                                     ])
96                                 );
97                             }
98                         }
99                         sourceSplit = true;
100                         splits = splits[1];
101                     }
102                     if(splits.length) {
103                         // splice in new target parts
104                         splits.unshift(j, 1);
105                         Array.prototype.splice.apply(targetParts, splits);
106                         break;
107                     }
108                 }
109             }
110             if(!sourceSplit) {
111                 // source line was not hit
112                 if(sourceParts.length) {
113                     // add line to existing multi
114                     sourceParts[sourceParts.length-1].addComponent(
115                         sourceLine.clone()
116                     );
117                 } else {
118                     // create a fresh multi
119                     sourceParts = [
120                         new OpenLayers.Geometry.MultiLineString(
121                             sourceLine.clone()
122                         )
123                     ];
124                 }
125             }
126         }
127         if(sourceParts && sourceParts.length > 1) {
128             sourceSplit = true;
129         } else {
130             sourceParts = [];
131         }
132         if(targetParts && targetParts.length > 1) {
133             targetSplit = true;
134         } else {
135             targetParts = [];
136         }
137         if(sourceSplit || targetSplit) {
138             if(mutual) {
139                 results = [sourceParts, targetParts];
140             } else {
141                 results = targetParts;
142             }
143         }
144         return results;
145     },
146     
147     /**
148      * Method: splitWith
149      * Split this geometry (the target) with the given geometry (the source).
150      *
151      * Parameters:
152      * geometry - {<OpenLayers.Geometry>} A geometry used to split this
153      *     geometry (the source).
154      * options - {Object} Properties of this object will be used to determine
155      *     how the split is conducted.
156      *
157      * Valid options:
158      * mutual - {Boolean} Split the source geometry in addition to the target
159      *     geometry.  Default is false.
160      * edge - {Boolean} Allow splitting when only edges intersect.  Default is
161      *     true.  If false, a vertex on the source must be within the tolerance
162      *     distance of the intersection to be considered a split.
163      * tolerance - {Number} If a non-null value is provided, intersections
164      *     within the tolerance distance of an existing vertex on the source
165      *     will be assumed to occur at the vertex.
166      * 
167      * Returns:
168      * {Array} A list of geometries (of this same type as the target) that
169      *     result from splitting the target with the source geometry.  The
170      *     source and target geometry will remain unmodified.  If no split
171      *     results, null will be returned.  If mutual is true and a split
172      *     results, return will be an array of two arrays - the first will be
173      *     all geometries that result from splitting the source geometry and
174      *     the second will be all geometries that result from splitting the
175      *     target geometry.
176      */
177     splitWith: function(geometry, options) {
178         var results = null;
179         var mutual = options && options.mutual;
180         var splits, targetLine, sourceLines, sourceSplit, targetSplit, sourceParts, targetParts;
181         if(geometry instanceof OpenLayers.Geometry.LineString) {
182             targetParts = [];
183             sourceParts = [geometry];
184             for(var i=0, len=this.components.length; i<len; ++i) {
185                 targetSplit = false;
186                 targetLine = this.components[i];
187                 for(var j=0; j<sourceParts.length; ++j) {
188                     splits = sourceParts[j].split(targetLine, options);
189                     if(splits) {
190                         if(mutual) {
191                             sourceLines = splits[0];
192                             if(sourceLines.length) {
193                                 // splice in new source parts
194                                 sourceLines.unshift(j, 1);
195                                 Array.prototype.splice.apply(sourceParts, sourceLines);
196                                 j += sourceLines.length - 2;
197                             }
198                             splits = splits[1];
199                             if(splits.length === 0) {
200                                 splits = [targetLine.clone()];
201                             }
202                         }
203                         for(var k=0, klen=splits.length; k<klen; ++k) {
204                             if(k===0 && targetParts.length) {
205                                 targetParts[targetParts.length-1].addComponent(
206                                     splits[k]
207                                 );
208                             } else {
209                                 targetParts.push(
210                                     new OpenLayers.Geometry.MultiLineString([
211                                         splits[k]
212                                     ])
213                                 );
214                             }
215                         }
216                         targetSplit = true;                    
217                     }
218                 }
219                 if(!targetSplit) {
220                     // target component was not hit
221                     if(targetParts.length) {
222                         // add it to any existing multi-line
223                         targetParts[targetParts.length-1].addComponent(
224                             targetLine.clone()
225                         );
226                     } else {
227                         // or start with a fresh multi-line
228                         targetParts = [
229                             new OpenLayers.Geometry.MultiLineString([
230                                 targetLine.clone()
231                             ])
232                         ];
233                     }
234                     
235                 }
236             }
237         } else {
238             results = geometry.split(this);
239         }
240         if(sourceParts && sourceParts.length > 1) {
241             sourceSplit = true;
242         } else {
243             sourceParts = [];
244         }
245         if(targetParts && targetParts.length > 1) {
246             targetSplit = true;
247         } else {
248             targetParts = [];
249         }
250         if(sourceSplit || targetSplit) {
251             if(mutual) {
252                 results = [sourceParts, targetParts];
253             } else {
254                 results = targetParts;
255             }
256         }
257         return results;
258     },
259
260     CLASS_NAME: "OpenLayers.Geometry.MultiLineString"
261 });