DouglasPeuckerLineSimplifier.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import CoordinateList from '../geom/CoordinateList'
  2. import Coordinate from '../geom/Coordinate'
  3. import LineSegment from '../geom/LineSegment'
  4. export default class DouglasPeuckerLineSimplifier {
  5. constructor() {
  6. DouglasPeuckerLineSimplifier.constructor_.apply(this, arguments)
  7. }
  8. static constructor_() {
  9. this._pts = null
  10. this._usePt = null
  11. this._distanceTolerance = null
  12. this._seg = new LineSegment()
  13. const pts = arguments[0]
  14. this._pts = pts
  15. }
  16. static simplify(pts, distanceTolerance) {
  17. const simp = new DouglasPeuckerLineSimplifier(pts)
  18. simp.setDistanceTolerance(distanceTolerance)
  19. return simp.simplify()
  20. }
  21. simplifySection(i, j) {
  22. if (i + 1 === j)
  23. return null
  24. this._seg.p0 = this._pts[i]
  25. this._seg.p1 = this._pts[j]
  26. let maxDistance = -1.0
  27. let maxIndex = i
  28. for (let k = i + 1; k < j; k++) {
  29. const distance = this._seg.distance(this._pts[k])
  30. if (distance > maxDistance) {
  31. maxDistance = distance
  32. maxIndex = k
  33. }
  34. }
  35. if (maxDistance <= this._distanceTolerance) {
  36. for (let k = i + 1; k < j; k++)
  37. this._usePt[k] = false
  38. } else {
  39. this.simplifySection(i, maxIndex)
  40. this.simplifySection(maxIndex, j)
  41. }
  42. }
  43. setDistanceTolerance(distanceTolerance) {
  44. this._distanceTolerance = distanceTolerance
  45. }
  46. simplify() {
  47. this._usePt = new Array(this._pts.length).fill(null)
  48. for (let i = 0; i < this._pts.length; i++)
  49. this._usePt[i] = true
  50. this.simplifySection(0, this._pts.length - 1)
  51. const coordList = new CoordinateList()
  52. for (let i = 0; i < this._pts.length; i++)
  53. if (this._usePt[i]) coordList.add(new Coordinate(this._pts[i]))
  54. return coordList.toCoordinateArray()
  55. }
  56. }