index.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import centroid from "@turf/centroid";
  2. import { getCoord } from "@turf/invariant";
  3. import { featureEach } from "@turf/meta";
  4. /**
  5. * calcualte the Minkowski p-norm distance between two features.
  6. * @param feature1 point feature
  7. * @param feature2 point feature
  8. * @param p p-norm 1=<p<=infinity 1: Manhattan distance 2: Euclidean distance
  9. */
  10. export function pNormDistance(feature1, feature2, p) {
  11. if (p === void 0) { p = 2; }
  12. var coordinate1 = getCoord(feature1);
  13. var coordinate2 = getCoord(feature2);
  14. var xDiff = coordinate1[0] - coordinate2[0];
  15. var yDiff = coordinate1[1] - coordinate2[1];
  16. if (p === 1) {
  17. return Math.abs(xDiff) + Math.abs(yDiff);
  18. }
  19. return Math.pow(Math.pow(xDiff, p) + Math.pow(yDiff, p), 1 / p);
  20. }
  21. /**
  22. *
  23. *
  24. * @name distanceWeight
  25. * @param {FeatureCollection<any>} fc FeatureCollection.
  26. * @param {Object} [options] option object.
  27. * @param {number} [options.threshold=10000] If the distance between neighbor and
  28. * target features is greater than threshold, the weight of that neighbor is 0.
  29. * @param {number} [options.p=2] Minkowski p-norm distance parameter.
  30. * 1: Manhattan distance. 2: Euclidean distance. 1=<p<=infinity.
  31. * @param {boolean} [options.binary=false] If true, weight=1 if d <= threshold otherwise weight=0.
  32. * If false, weight=Math.pow(d, alpha).
  33. * @param {number} [options.alpha=-1] distance decay parameter.
  34. * A big value means the weight decay quickly as distance increases.
  35. * @param {boolean} [options.standardization=false] row standardization.
  36. * @returns {Array<Array<number>>} distance weight matrix.
  37. * @example
  38. *
  39. * var bbox = [-65, 40, -63, 42];
  40. * var dataset = turf.randomPoint(100, { bbox: bbox });
  41. * var result = turf.distanceWeight(dataset);
  42. */
  43. export default function distanceWeight(fc, options) {
  44. options = options || {};
  45. var threshold = options.threshold || 10000;
  46. var p = options.p || 2;
  47. var binary = options.binary || false;
  48. var alpha = options.alpha || -1;
  49. var rowTransform = options.standardization || false;
  50. var features = [];
  51. featureEach(fc, function (feature) {
  52. features.push(centroid(feature));
  53. });
  54. // computing the distance between the features
  55. var weights = [];
  56. for (var i = 0; i < features.length; i++) {
  57. weights[i] = [];
  58. }
  59. for (var i = 0; i < features.length; i++) {
  60. for (var j = i; j < features.length; j++) {
  61. if (i === j) {
  62. weights[i][j] = 0;
  63. }
  64. var dis = pNormDistance(features[i], features[j], p);
  65. weights[i][j] = dis;
  66. weights[j][i] = dis;
  67. }
  68. }
  69. // binary or distance decay
  70. for (var i = 0; i < features.length; i++) {
  71. for (var j = 0; j < features.length; j++) {
  72. var dis = weights[i][j];
  73. if (dis === 0) {
  74. continue;
  75. }
  76. if (binary) {
  77. if (dis <= threshold) {
  78. weights[i][j] = 1.0;
  79. }
  80. else {
  81. weights[i][j] = 0.0;
  82. }
  83. }
  84. else {
  85. if (dis <= threshold) {
  86. weights[i][j] = Math.pow(dis, alpha);
  87. }
  88. else {
  89. weights[i][j] = 0.0;
  90. }
  91. }
  92. }
  93. }
  94. if (rowTransform) {
  95. for (var i = 0; i < features.length; i++) {
  96. var rowSum = weights[i].reduce(function (sum, currentVal) {
  97. return sum + currentVal;
  98. }, 0);
  99. for (var j = 0; j < features.length; j++) {
  100. weights[i][j] = weights[i][j] / rowSum;
  101. }
  102. }
  103. }
  104. return weights;
  105. }