MultiLineString.js 10 KB

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