"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// index.ts
var _meta = require('@turf/meta');
var _helpers = require('@turf/helpers');

// lib/geojson-polygon-self-intersections.js
var _rbush = require('rbush'); var _rbush2 = _interopRequireDefault(_rbush);
function geojsonPolygonSelfIntersections(feature, filterFn, useSpatialIndex) {
  if (feature.geometry.type !== "Polygon")
    throw new Error("The input feature must be a Polygon");
  if (useSpatialIndex === void 0) useSpatialIndex = 1;
  var coord = feature.geometry.coordinates;
  var output = [];
  var seen = {};
  if (useSpatialIndex) {
    var allEdgesAsRbushTreeItems = [];
    for (var ring0 = 0; ring0 < coord.length; ring0++) {
      for (var edge0 = 0; edge0 < coord[ring0].length - 1; edge0++) {
        allEdgesAsRbushTreeItems.push(rbushTreeItem(ring0, edge0));
      }
    }
    var tree = new (0, _rbush2.default)();
    tree.load(allEdgesAsRbushTreeItems);
  }
  for (var ringA = 0; ringA < coord.length; ringA++) {
    for (var edgeA = 0; edgeA < coord[ringA].length - 1; edgeA++) {
      if (useSpatialIndex) {
        var bboxOverlaps = tree.search(rbushTreeItem(ringA, edgeA));
        bboxOverlaps.forEach(function(bboxIsect) {
          var ring12 = bboxIsect.ring;
          var edge12 = bboxIsect.edge;
          ifIsectAddToOutput(ringA, edgeA, ring12, edge12);
        });
      } else {
        for (var ring1 = 0; ring1 < coord.length; ring1++) {
          for (var edge1 = 0; edge1 < coord[ring1].length - 1; edge1++) {
            ifIsectAddToOutput(ringA, edgeA, ring1, edge1);
          }
        }
      }
    }
  }
  if (!filterFn)
    output = {
      type: "Feature",
      geometry: { type: "MultiPoint", coordinates: output }
    };
  return output;
  function ifIsectAddToOutput(ring02, edge02, ring12, edge12) {
    var start0 = coord[ring02][edge02];
    var end0 = coord[ring02][edge02 + 1];
    var start1 = coord[ring12][edge12];
    var end1 = coord[ring12][edge12 + 1];
    var isect = intersect(start0, end0, start1, end1);
    if (isect === null) return;
    var frac0;
    var frac1;
    if (end0[0] !== start0[0]) {
      frac0 = (isect[0] - start0[0]) / (end0[0] - start0[0]);
    } else {
      frac0 = (isect[1] - start0[1]) / (end0[1] - start0[1]);
    }
    if (end1[0] !== start1[0]) {
      frac1 = (isect[0] - start1[0]) / (end1[0] - start1[0]);
    } else {
      frac1 = (isect[1] - start1[1]) / (end1[1] - start1[1]);
    }
    if (frac0 >= 1 || frac0 <= 0 || frac1 >= 1 || frac1 <= 0) return;
    var key = isect;
    var unique = !seen[key];
    if (unique) {
      seen[key] = true;
    }
    if (filterFn) {
      output.push(
        filterFn(
          isect,
          ring02,
          edge02,
          start0,
          end0,
          frac0,
          ring12,
          edge12,
          start1,
          end1,
          frac1,
          unique
        )
      );
    } else {
      output.push(isect);
    }
  }
  function rbushTreeItem(ring, edge) {
    var start = coord[ring][edge];
    var end = coord[ring][edge + 1];
    var minX;
    var maxX;
    var minY;
    var maxY;
    if (start[0] < end[0]) {
      minX = start[0];
      maxX = end[0];
    } else {
      minX = end[0];
      maxX = start[0];
    }
    if (start[1] < end[1]) {
      minY = start[1];
      maxY = end[1];
    } else {
      minY = end[1];
      maxY = start[1];
    }
    return {
      minX,
      minY,
      maxX,
      maxY,
      ring,
      edge
    };
  }
}
function intersect(start0, end0, start1, end1) {
  if (equalArrays(start0, start1) || equalArrays(start0, end1) || equalArrays(end0, start1) || equalArrays(end1, start1))
    return null;
  var x0 = start0[0], y0 = start0[1], x1 = end0[0], y1 = end0[1], x2 = start1[0], y2 = start1[1], x3 = end1[0], y3 = end1[1];
  var denom = (x0 - x1) * (y2 - y3) - (y0 - y1) * (x2 - x3);
  if (denom === 0) return null;
  var x4 = ((x0 * y1 - y0 * x1) * (x2 - x3) - (x0 - x1) * (x2 * y3 - y2 * x3)) / denom;
  var y4 = ((x0 * y1 - y0 * x1) * (y2 - y3) - (y0 - y1) * (x2 * y3 - y2 * x3)) / denom;
  return [x4, y4];
}
function equalArrays(array1, array2) {
  if (!array1 || !array2) return false;
  if (array1.length !== array2.length) return false;
  for (var i = 0, l = array1.length; i < l; i++) {
    if (array1[i] instanceof Array && array2[i] instanceof Array) {
      if (!equalArrays(array1[i], array2[i])) return false;
    } else if (array1[i] !== array2[i]) {
      return false;
    }
  }
  return true;
}

// lib/simplepolygon.js
var _area = require('@turf/area');

var _booleanpointinpolygon = require('@turf/boolean-point-in-polygon');

function simplepolygon(feature) {
  if (feature.type != "Feature")
    throw new Error("The input must a geojson object of type Feature");
  if (feature.geometry === void 0 || feature.geometry == null)
    throw new Error(
      "The input must a geojson object with a non-empty geometry"
    );
  if (feature.geometry.type != "Polygon")
    throw new Error("The input must be a geojson Polygon");
  var numRings = feature.geometry.coordinates.length;
  var vertices = [];
  for (var i = 0; i < numRings; i++) {
    var ring = feature.geometry.coordinates[i];
    if (!equalArrays2(ring[0], ring[ring.length - 1])) {
      ring.push(ring[0]);
    }
    for (var j = 0; j < ring.length - 1; j++) {
      vertices.push(ring[j]);
    }
  }
  if (!isUnique(vertices))
    throw new Error(
      "The input polygon may not have duplicate vertices (except for the first and last vertex of each ring)"
    );
  var numvertices = vertices.length;
  var selfIsectsData = geojsonPolygonSelfIntersections(
    feature,
    function filterFn(isect, ring0, edge0, start0, end0, frac0, ring1, edge1, start1, end1, frac1, unique) {
      return [
        isect,
        ring0,
        edge0,
        start0,
        end0,
        frac0,
        ring1,
        edge1,
        start1,
        end1,
        frac1,
        unique
      ];
    }
  );
  var numSelfIsect = selfIsectsData.length;
  if (numSelfIsect == 0) {
    var outputFeatureArray = [];
    for (var i = 0; i < numRings; i++) {
      outputFeatureArray.push(
        _helpers.polygon.call(void 0, [feature.geometry.coordinates[i]], {
          parent: -1,
          winding: windingOfRing(feature.geometry.coordinates[i])
        })
      );
    }
    var output = _helpers.featureCollection.call(void 0, outputFeatureArray);
    determineParents();
    setNetWinding();
    return output;
  }
  var pseudoVtxListByRingAndEdge = [];
  var isectList = [];
  for (var i = 0; i < numRings; i++) {
    pseudoVtxListByRingAndEdge.push([]);
    for (var j = 0; j < feature.geometry.coordinates[i].length - 1; j++) {
      pseudoVtxListByRingAndEdge[i].push([
        new PseudoVtx(
          feature.geometry.coordinates[i][modulo(j + 1, feature.geometry.coordinates[i].length - 1)],
          1,
          [i, j],
          [i, modulo(j + 1, feature.geometry.coordinates[i].length - 1)],
          void 0
        )
      ]);
      isectList.push(
        new Isect(
          feature.geometry.coordinates[i][j],
          [i, modulo(j - 1, feature.geometry.coordinates[i].length - 1)],
          [i, j],
          void 0,
          void 0,
          false,
          true
        )
      );
    }
  }
  for (var i = 0; i < numSelfIsect; i++) {
    pseudoVtxListByRingAndEdge[selfIsectsData[i][1]][selfIsectsData[i][2]].push(
      new PseudoVtx(
        selfIsectsData[i][0],
        selfIsectsData[i][5],
        [selfIsectsData[i][1], selfIsectsData[i][2]],
        [selfIsectsData[i][6], selfIsectsData[i][7]],
        void 0
      )
    );
    if (selfIsectsData[i][11])
      isectList.push(
        new Isect(
          selfIsectsData[i][0],
          [selfIsectsData[i][1], selfIsectsData[i][2]],
          [selfIsectsData[i][6], selfIsectsData[i][7]],
          void 0,
          void 0,
          true,
          true
        )
      );
  }
  var numIsect = isectList.length;
  for (var i = 0; i < pseudoVtxListByRingAndEdge.length; i++) {
    for (var j = 0; j < pseudoVtxListByRingAndEdge[i].length; j++) {
      pseudoVtxListByRingAndEdge[i][j].sort(function(a, b) {
        return a.param < b.param ? -1 : 1;
      });
    }
  }
  var allIsectsAsIsectRbushTreeItem = [];
  for (var i = 0; i < numIsect; i++) {
    allIsectsAsIsectRbushTreeItem.push({
      minX: isectList[i].coord[0],
      minY: isectList[i].coord[1],
      maxX: isectList[i].coord[0],
      maxY: isectList[i].coord[1],
      index: i
    });
  }
  var isectRbushTree = new (0, _rbush2.default)();
  isectRbushTree.load(allIsectsAsIsectRbushTreeItem);
  for (var i = 0; i < pseudoVtxListByRingAndEdge.length; i++) {
    for (var j = 0; j < pseudoVtxListByRingAndEdge[i].length; j++) {
      for (var k = 0; k < pseudoVtxListByRingAndEdge[i][j].length; k++) {
        var coordToFind;
        if (k == pseudoVtxListByRingAndEdge[i][j].length - 1) {
          coordToFind = pseudoVtxListByRingAndEdge[i][modulo(j + 1, feature.geometry.coordinates[i].length - 1)][0].coord;
        } else {
          coordToFind = pseudoVtxListByRingAndEdge[i][j][k + 1].coord;
        }
        var IsectRbushTreeItemFound = isectRbushTree.search({
          minX: coordToFind[0],
          minY: coordToFind[1],
          maxX: coordToFind[0],
          maxY: coordToFind[1]
        })[0];
        pseudoVtxListByRingAndEdge[i][j][k].nxtIsectAlongEdgeIn = IsectRbushTreeItemFound.index;
      }
    }
  }
  for (var i = 0; i < pseudoVtxListByRingAndEdge.length; i++) {
    for (var j = 0; j < pseudoVtxListByRingAndEdge[i].length; j++) {
      for (var k = 0; k < pseudoVtxListByRingAndEdge[i][j].length; k++) {
        var coordToFind = pseudoVtxListByRingAndEdge[i][j][k].coord;
        var IsectRbushTreeItemFound = isectRbushTree.search({
          minX: coordToFind[0],
          minY: coordToFind[1],
          maxX: coordToFind[0],
          maxY: coordToFind[1]
        })[0];
        var l = IsectRbushTreeItemFound.index;
        if (l < numvertices) {
          isectList[l].nxtIsectAlongRingAndEdge2 = pseudoVtxListByRingAndEdge[i][j][k].nxtIsectAlongEdgeIn;
        } else {
          if (equalArrays2(
            isectList[l].ringAndEdge1,
            pseudoVtxListByRingAndEdge[i][j][k].ringAndEdgeIn
          )) {
            isectList[l].nxtIsectAlongRingAndEdge1 = pseudoVtxListByRingAndEdge[i][j][k].nxtIsectAlongEdgeIn;
          } else {
            isectList[l].nxtIsectAlongRingAndEdge2 = pseudoVtxListByRingAndEdge[i][j][k].nxtIsectAlongEdgeIn;
          }
        }
      }
    }
  }
  var queue = [];
  var i = 0;
  for (var j = 0; j < numRings; j++) {
    var leftIsect = i;
    for (var k = 0; k < feature.geometry.coordinates[j].length - 1; k++) {
      if (isectList[i].coord[0] < isectList[leftIsect].coord[0]) {
        leftIsect = i;
      }
      i++;
    }
    var isectAfterLeftIsect = isectList[leftIsect].nxtIsectAlongRingAndEdge2;
    for (var k = 0; k < isectList.length; k++) {
      if (isectList[k].nxtIsectAlongRingAndEdge1 == leftIsect || isectList[k].nxtIsectAlongRingAndEdge2 == leftIsect) {
        var isectBeforeLeftIsect = k;
        break;
      }
    }
    var windingAtIsect = isConvex(
      [
        isectList[isectBeforeLeftIsect].coord,
        isectList[leftIsect].coord,
        isectList[isectAfterLeftIsect].coord
      ],
      true
    ) ? 1 : -1;
    queue.push({ isect: leftIsect, parent: -1, winding: windingAtIsect });
  }
  queue.sort(function(a, b) {
    return isectList[a.isect].coord > isectList[b.isect].coord ? -1 : 1;
  });
  var outputFeatureArray = [];
  while (queue.length > 0) {
    var popped = queue.pop();
    var startIsect = popped.isect;
    var currentOutputRingParent = popped.parent;
    var currentOutputRingWinding = popped.winding;
    var currentOutputRing = outputFeatureArray.length;
    var currentOutputRingCoords = [isectList[startIsect].coord];
    var currentIsect = startIsect;
    if (isectList[startIsect].ringAndEdge1Walkable) {
      var walkingRingAndEdge = isectList[startIsect].ringAndEdge1;
      var nxtIsect = isectList[startIsect].nxtIsectAlongRingAndEdge1;
    } else {
      var walkingRingAndEdge = isectList[startIsect].ringAndEdge2;
      var nxtIsect = isectList[startIsect].nxtIsectAlongRingAndEdge2;
    }
    while (!equalArrays2(isectList[startIsect].coord, isectList[nxtIsect].coord)) {
      currentOutputRingCoords.push(isectList[nxtIsect].coord);
      var nxtIsectInQueue = void 0;
      for (var i = 0; i < queue.length; i++) {
        if (queue[i].isect == nxtIsect) {
          nxtIsectInQueue = i;
          break;
        }
      }
      if (nxtIsectInQueue != void 0) {
        queue.splice(nxtIsectInQueue, 1);
      }
      if (equalArrays2(walkingRingAndEdge, isectList[nxtIsect].ringAndEdge1)) {
        walkingRingAndEdge = isectList[nxtIsect].ringAndEdge2;
        isectList[nxtIsect].ringAndEdge2Walkable = false;
        if (isectList[nxtIsect].ringAndEdge1Walkable) {
          var pushing = { isect: nxtIsect };
          if (isConvex(
            [
              isectList[currentIsect].coord,
              isectList[nxtIsect].coord,
              isectList[isectList[nxtIsect].nxtIsectAlongRingAndEdge2].coord
            ],
            currentOutputRingWinding == 1
          )) {
            pushing.parent = currentOutputRingParent;
            pushing.winding = -currentOutputRingWinding;
          } else {
            pushing.parent = currentOutputRing;
            pushing.winding = currentOutputRingWinding;
          }
          queue.push(pushing);
        }
        currentIsect = nxtIsect;
        nxtIsect = isectList[nxtIsect].nxtIsectAlongRingAndEdge2;
      } else {
        walkingRingAndEdge = isectList[nxtIsect].ringAndEdge1;
        isectList[nxtIsect].ringAndEdge1Walkable = false;
        if (isectList[nxtIsect].ringAndEdge2Walkable) {
          var pushing = { isect: nxtIsect };
          if (isConvex(
            [
              isectList[currentIsect].coord,
              isectList[nxtIsect].coord,
              isectList[isectList[nxtIsect].nxtIsectAlongRingAndEdge1].coord
            ],
            currentOutputRingWinding == 1
          )) {
            pushing.parent = currentOutputRingParent;
            pushing.winding = -currentOutputRingWinding;
          } else {
            pushing.parent = currentOutputRing;
            pushing.winding = currentOutputRingWinding;
          }
          queue.push(pushing);
        }
        currentIsect = nxtIsect;
        nxtIsect = isectList[nxtIsect].nxtIsectAlongRingAndEdge1;
      }
    }
    currentOutputRingCoords.push(isectList[nxtIsect].coord);
    outputFeatureArray.push(
      _helpers.polygon.call(void 0, [currentOutputRingCoords], {
        index: currentOutputRing,
        parent: currentOutputRingParent,
        winding: currentOutputRingWinding,
        netWinding: void 0
      })
    );
  }
  var output = _helpers.featureCollection.call(void 0, outputFeatureArray);
  determineParents();
  setNetWinding();
  function determineParents() {
    var featuresWithoutParent = [];
    for (var i2 = 0; i2 < output.features.length; i2++) {
      if (output.features[i2].properties.parent == -1)
        featuresWithoutParent.push(i2);
    }
    if (featuresWithoutParent.length > 1) {
      for (var i2 = 0; i2 < featuresWithoutParent.length; i2++) {
        var parent = -1;
        var parentArea = Infinity;
        for (var j2 = 0; j2 < output.features.length; j2++) {
          if (featuresWithoutParent[i2] == j2) continue;
          if (_booleanpointinpolygon.booleanPointInPolygon.call(void 0, 
            output.features[featuresWithoutParent[i2]].geometry.coordinates[0][0],
            output.features[j2],
            { ignoreBoundary: true }
          )) {
            if (_area.area.call(void 0, output.features[j2]) < parentArea) {
              parent = j2;
            }
          }
        }
        output.features[featuresWithoutParent[i2]].properties.parent = parent;
      }
    }
  }
  function setNetWinding() {
    for (var i2 = 0; i2 < output.features.length; i2++) {
      if (output.features[i2].properties.parent == -1) {
        var netWinding = output.features[i2].properties.winding;
        output.features[i2].properties.netWinding = netWinding;
        setNetWindingOfChildren(i2, netWinding);
      }
    }
  }
  function setNetWindingOfChildren(parent, ParentNetWinding) {
    for (var i2 = 0; i2 < output.features.length; i2++) {
      if (output.features[i2].properties.parent == parent) {
        var netWinding = ParentNetWinding + output.features[i2].properties.winding;
        output.features[i2].properties.netWinding = netWinding;
        setNetWindingOfChildren(i2, netWinding);
      }
    }
  }
  return output;
}
var PseudoVtx = function(coord, param, ringAndEdgeIn, ringAndEdgeOut, nxtIsectAlongEdgeIn) {
  this.coord = coord;
  this.param = param;
  this.ringAndEdgeIn = ringAndEdgeIn;
  this.ringAndEdgeOut = ringAndEdgeOut;
  this.nxtIsectAlongEdgeIn = nxtIsectAlongEdgeIn;
};
var Isect = function(coord, ringAndEdge1, ringAndEdge2, nxtIsectAlongRingAndEdge1, nxtIsectAlongRingAndEdge2, ringAndEdge1Walkable, ringAndEdge2Walkable) {
  this.coord = coord;
  this.ringAndEdge1 = ringAndEdge1;
  this.ringAndEdge2 = ringAndEdge2;
  this.nxtIsectAlongRingAndEdge1 = nxtIsectAlongRingAndEdge1;
  this.nxtIsectAlongRingAndEdge2 = nxtIsectAlongRingAndEdge2;
  this.ringAndEdge1Walkable = ringAndEdge1Walkable;
  this.ringAndEdge2Walkable = ringAndEdge2Walkable;
};
function isConvex(pts, righthanded) {
  if (typeof righthanded === "undefined") righthanded = true;
  if (pts.length != 3)
    throw new Error("This function requires an array of three points [x,y]");
  var d = (pts[1][0] - pts[0][0]) * (pts[2][1] - pts[0][1]) - (pts[1][1] - pts[0][1]) * (pts[2][0] - pts[0][0]);
  return d >= 0 == righthanded;
}
function windingOfRing(ring) {
  var leftVtx = 0;
  for (var i = 0; i < ring.length - 1; i++) {
    if (ring[i][0] < ring[leftVtx][0]) leftVtx = i;
  }
  if (isConvex(
    [
      ring[modulo(leftVtx - 1, ring.length - 1)],
      ring[leftVtx],
      ring[modulo(leftVtx + 1, ring.length - 1)]
    ],
    true
  )) {
    var winding = 1;
  } else {
    var winding = -1;
  }
  return winding;
}
function equalArrays2(array1, array2) {
  if (!array1 || !array2) return false;
  if (array1.length != array2.length) return false;
  for (var i = 0, l = array1.length; i < l; i++) {
    if (array1[i] instanceof Array && array2[i] instanceof Array) {
      if (!equalArrays2(array1[i], array2[i])) return false;
    } else if (array1[i] != array2[i]) {
      return false;
    }
  }
  return true;
}
function modulo(n, m) {
  return (n % m + m) % m;
}
function isUnique(array) {
  var u = {};
  var isUnique2 = 1;
  for (var i = 0, l = array.length; i < l; ++i) {
    if (Object.prototype.hasOwnProperty.call(u, array[i])) {
      isUnique2 = 0;
      break;
    }
    u[array[i]] = 1;
  }
  return isUnique2;
}

// index.ts
function unkinkPolygon(geojson) {
  var features = [];
  _meta.flattenEach.call(void 0, geojson, function(feature) {
    if (feature.geometry.type !== "Polygon") return;
    _meta.featureEach.call(void 0, simplepolygon(feature), function(poly) {
      features.push(_helpers.polygon.call(void 0, poly.geometry.coordinates, feature.properties));
    });
  });
  return _helpers.featureCollection.call(void 0, features);
}
var turf_unkink_polygon_default = unkinkPolygon;



exports.default = turf_unkink_polygon_default; exports.unkinkPolygon = unkinkPolygon;
//# sourceMappingURL=index.cjs.map