AMapUI.weakDefine("ui/geo/DistrictExplorer/lib/Const", [], function() {
    return {
        BBRFLAG: {
            I: 1,
            S: 2
        },
        ADCODES: {
            COUNTRY: 1e5
        }
    };
});

AMapUI.weakDefine("ui/geo/DistrictExplorer/lib/geomUtils", [], function() {
    function polygonClip(subjectPolygon, clipPolygon) {
        var cp1, cp2, s, e, outputList = subjectPolygon;
        cp1 = clipPolygon[clipPolygon.length - 2];
        for (var j = 0, jlen = clipPolygon.length - 1; j < jlen; j++) {
            cp2 = clipPolygon[j];
            var inputList = outputList;
            outputList = [];
            s = inputList[inputList.length - 1];
            for (var i = 0, len = inputList.length; i < len; i++) {
                e = inputList[i];
                if (clipInside(e, cp1, cp2)) {
                    clipInside(s, cp1, cp2) || outputList.push(clipIntersection(cp1, cp2, s, e));
                    outputList.push(e);
                } else clipInside(s, cp1, cp2) && outputList.push(clipIntersection(cp1, cp2, s, e));
                s = e;
            }
            cp1 = cp2;
        }
        if (outputList.length < 3) return [];
        outputList.push(outputList[0]);
        return outputList;
    }
    function pointOnSegment(p, p1, p2) {
        var tx = (p2[1] - p1[1]) / (p2[0] - p1[0]) * (p[0] - p1[0]) + p1[1];
        return Math.abs(tx - p[1]) < 1e-6 && p[0] >= p1[0] && p[0] <= p2[0];
    }
    function pointOnPolygon(point, vs) {
        for (var i = 0, len = vs.length; i < len - 1; i++) if (pointOnSegment(point, vs[i], vs[i + 1])) return !0;
        return !1;
    }
    function pointInPolygon(point, vs) {
        for (var x = point[0], y = point[1], inside = !1, i = 0, len = vs.length, j = len - 1; i < len; j = i++) {
            var xi = vs[i][0], yi = vs[i][1], xj = vs[j][0], yj = vs[j][1], intersect = yi > y != yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi;
            intersect && (inside = !inside);
        }
        return inside;
    }
    function getClosestPointOnSegment(p, p1, p2) {
        var t, x = p1[0], y = p1[1], dx = p2[0] - x, dy = p2[1] - y, dot = dx * dx + dy * dy;
        if (dot > 0) {
            t = ((p[0] - x) * dx + (p[1] - y) * dy) / dot;
            if (t > 1) {
                x = p2[0];
                y = p2[1];
            } else if (t > 0) {
                x += dx * t;
                y += dy * t;
            }
        }
        return [ x, y ];
    }
    function sqClosestDistanceToSegment(p, p1, p2) {
        var p3 = getClosestPointOnSegment(p, p1, p2), dx = p[0] - p3[0], dy = p[1] - p3[1];
        return dx * dx + dy * dy;
    }
    function sqClosestDistanceToPolygon(p, points) {
        for (var minSq = Number.MAX_VALUE, i = 0, len = points.length; i < len - 1; i++) {
            var sq = sqClosestDistanceToSegment(p, points[i], points[i + 1]);
            sq < minSq && (minSq = sq);
        }
        return minSq;
    }
    var clipInside = function(p, cp1, cp2) {
        return (cp2[0] - cp1[0]) * (p[1] - cp1[1]) > (cp2[1] - cp1[1]) * (p[0] - cp1[0]);
    }, clipIntersection = function(cp1, cp2, s, e) {
        var dc = [ cp1[0] - cp2[0], cp1[1] - cp2[1] ], dp = [ s[0] - e[0], s[1] - e[1] ], n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0], n2 = s[0] * e[1] - s[1] * e[0], n3 = 1 / (dc[0] * dp[1] - dc[1] * dp[0]);
        return [ (n1 * dp[0] - n2 * dc[0]) * n3, (n1 * dp[1] - n2 * dc[1]) * n3 ];
    };
    return {
        sqClosestDistanceToPolygon: sqClosestDistanceToPolygon,
        sqClosestDistanceToSegment: sqClosestDistanceToSegment,
        pointOnSegment: pointOnSegment,
        pointOnPolygon: pointOnPolygon,
        pointInPolygon: pointInPolygon,
        polygonClip: polygonClip
    };
});

AMapUI.weakDefine("ui/geo/DistrictExplorer/lib/bbIdxBuilder", [ "./Const", "./geomUtils" ], function(Const, geomUtils) {
    function parseRanges(ranges, radix) {
        for (var nums = [], i = 0, len = ranges.length; i < len; i++) {
            var parts = ranges[i].split("-"), start = parts[0], end = parts.length > 1 ? parts[1] : start;
            start = parseInt(start, radix);
            end = parseInt(end, radix);
            for (var j = start; j <= end; j++) nums.push(j);
        }
        return nums;
    }
    function add2BBList(bbList, seqIdx, result) {
        if (bbList[seqIdx]) throw new Error("Alreay exists: ", bbList[seqIdx]);
        bbList[seqIdx] = result;
    }
    function getFlagI(idx) {
        flagIList[idx] || (flagIList[idx] = [ BBRFLAG.I, idx ]);
        return flagIList[idx];
    }
    function parseILine(line, radix, bbList) {
        if (line) for (var parts = line.split(":"), fIdx = parseInt(parts[0], radix), bIdxes = parseRanges(parts[1].split(","), radix), item = getFlagI(fIdx), i = 0, len = bIdxes.length; i < len; i++) add2BBList(bbList, bIdxes[i], item);
    }
    function parseSLine(line, radix, bbList) {
        if (line) {
            for (var item, parts = line.split(":"), bIdx = parseInt(parts[0], radix), fList = parts[1].split(";"), secList = [], i = 0, len = fList.length; i < len; i++) {
                parts = fList[i].split(",");
                item = [ parseInt(parts[0], radix), 0 ];
                parts.length > 1 && (item[1] = parseInt(parts[1], radix));
                secList.push(item);
            }
            add2BBList(bbList, bIdx, [ BBRFLAG.S, secList ]);
        }
    }
    function parseMaxRect(l, radix) {
        if (!l) return null;
        for (var parts = l.split(","), rect = [], i = 0, len = parts.length; i < len; i++) {
            var n = parseInt(parts[i], radix);
            if (n < 0) return null;
            rect.push(parseInt(parts[i], radix));
        }
        return rect;
    }
    function parseMultiMaxRect(l, radix) {
        if (!l) return null;
        for (var parts = l.split(";"), rectList = [], i = 0, len = parts.length; i < len; i++) rectList.push(parseMaxRect(parts[i], radix));
        return rectList;
    }
    function buildIdxList(res) {
        var i, len, radix = res.r, bbList = [], inList = res.idx.i.split("|");
        res.idx.i = null;
        for (i = 0, len = inList.length; i < len; i++) parseILine(inList[i], radix, bbList);
        inList.length = 0;
        var secList = res.idx.s.split("|");
        res.idx.s = null;
        for (i = 0, len = secList.length; i < len; i++) parseSLine(secList[i], radix, bbList);
        secList.length = 0;
        res.idx = null;
        res.idxList = bbList;
        if (res.mxr) {
            res.maxRect = parseMaxRect(res.mxr, radix);
            res.mxr = null;
        }
        if (res.mxsr) {
            res.maxSubRect = parseMultiMaxRect(res.mxsr, radix);
            res.mxsr = null;
        }
    }
    function buildRectFeatureClip(data, rect, ringIdxList) {
        for (var features = data.geoData.sub.features, i = 0, len = ringIdxList.length; i < len; i++) {
            var idxItem = ringIdxList[i], feature = features[idxItem[0]], ring = feature.geometry.coordinates[idxItem[1]][0], clipedRing = geomUtils.polygonClip(ring, rect);
            !clipedRing || clipedRing.length < 4 ? console.warn("Cliped ring length werid: " + clipedRing) : idxItem[2] = clipedRing;
        }
        return !0;
    }
    function prepareGridFeatureClip(data, x, y) {
        var bbIdx = data.bbIndex, step = bbIdx.s;
        (x < 0 || y < 0 || y >= bbIdx.h || x >= bbIdx.w) && console.warn("Wrong x,y", x, y, bbIdx);
        var seqIdx = y * bbIdx.w + x, idxItem = bbIdx.idxList[seqIdx];
        if (idxItem[0] !== BBRFLAG.S) return !1;
        var ringIdxList = idxItem[1];
        if (ringIdxList[0].length > 2) return !1;
        var rectX = x * step + bbIdx.l, rectY = y * step + bbIdx.t;
        buildRectFeatureClip(data, [ [ rectX, rectY ], [ rectX + step, rectY ], [ rectX + step, rectY + step ], [ rectX, rectY + step ], [ rectX, rectY ] ], ringIdxList);
        return !0;
    }
    var BBRFLAG = Const.BBRFLAG, flagIList = [];
    return {
        prepareGridFeatureClip: prepareGridFeatureClip,
        buildIdxList: buildIdxList
    };
});

AMapUI.weakDefine("ui/geo/DistrictExplorer/lib/BoundsItem", [ "lib/utils" ], function(utils) {
    function BoundsItem(x, y, width, height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
    utils.extend(BoundsItem, {
        getBoundsItemToExpand: function() {
            return new BoundsItem(Number.MAX_VALUE, Number.MAX_VALUE, -1, -1);
        },
        boundsContainPoint: function(b, p) {
            return b.x <= p.x && b.x + b.width >= p.x && b.y <= p.y && b.y + b.height >= p.y;
        },
        boundsContain: function(b1, b2) {
            return b1.x <= b2.x && b1.x + b1.width >= b2.x + b2.width && b1.y <= b2.y && b1.y + b1.height >= b2.y + b2.height;
        },
        boundsIntersect: function(b1, b2) {
            return b1.x <= b2.x + b2.width && b2.x <= b1.x + b1.width && b1.y <= b2.y + b2.height && b2.y <= b1.y + b1.height;
        }
    });
    utils.extend(BoundsItem.prototype, {
        containBounds: function(b) {
            return BoundsItem.boundsContain(this, b);
        },
        containPoint: function(p) {
            return BoundsItem.boundsContainPoint(this, p);
        },
        clone: function() {
            return new BoundsItem(this.x, this.y, this.width, this.height);
        },
        isEmpty: function() {
            return this.width < 0;
        },
        getMin: function() {
            return {
                x: this.x,
                y: this.y
            };
        },
        getMax: function() {
            return {
                x: this.x + this.width,
                y: this.y + this.height
            };
        },
        expandByPoint: function(x, y) {
            var minX, minY, maxX, maxY;
            if (this.isEmpty()) {
                minX = maxX = x;
                minY = maxY = y;
            } else {
                minX = this.x;
                minY = this.y;
                maxX = this.x + this.width;
                maxY = this.y + this.height;
                x < minX ? minX = x : x > maxX && (maxX = x);
                y < minY ? minY = y : y > maxY && (maxY = y);
            }
            this.x = minX;
            this.y = minY;
            this.width = maxX - minX;
            this.height = maxY - minY;
        },
        expandByBounds: function(bounds) {
            if (!bounds.isEmpty()) {
                var minX = this.x, minY = this.y, maxX = this.x + this.width, maxY = this.y + this.height, newMinX = bounds.x, newMaxX = bounds.x + bounds.width, newMinY = bounds.y, newMaxY = bounds.y + bounds.height;
                if (this.isEmpty()) {
                    minX = newMinX;
                    minY = newMinY;
                    maxX = newMaxX;
                    maxY = newMaxY;
                } else {
                    newMinX < minX && (minX = newMinX);
                    newMaxX > maxX && (maxX = newMaxX);
                    newMinY < minY && (minY = newMinY);
                    newMaxY > maxY && (maxY = newMaxY);
                }
                this.x = minX;
                this.y = minY;
                this.width = maxX - minX;
                this.height = maxY - minY;
            }
        },
        getTopLeft: function() {
            return {
                x: this.x,
                y: this.y
            };
        },
        getTopRight: function() {
            return {
                x: this.x + this.width,
                y: this.y
            };
        },
        getBottomLeft: function() {
            return {
                x: this.x,
                y: this.y + this.height
            };
        },
        getBottomRight: function() {
            return {
                x: this.x + this.width,
                y: this.y + this.height
            };
        }
    });
    return BoundsItem;
});

AMapUI.weakDefine("ui/geo/DistrictExplorer/ext/topojson-client", [ "exports" ], function(exports) {
    "use strict";
    function feature$1(topology, o) {
        var id = o.id, bbox = o.bbox, properties = null == o.properties ? {} : o.properties, geometry = object(topology, o);
        return null == id && null == bbox ? {
            type: "Feature",
            properties: properties,
            geometry: geometry
        } : null == bbox ? {
            type: "Feature",
            id: id,
            properties: properties,
            geometry: geometry
        } : {
            type: "Feature",
            id: id,
            bbox: bbox,
            properties: properties,
            geometry: geometry
        };
    }
    function object(topology, o) {
        function arc(i, points) {
            points.length && points.pop();
            for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) points.push(transformPoint(a[k], k));
            i < 0 && reverse(points, n);
        }
        function point(p) {
            return transformPoint(p);
        }
        function line(arcs) {
            for (var points = [], i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
            points.length < 2 && points.push(points[0]);
            return points;
        }
        function ring(arcs) {
            for (var points = line(arcs); points.length < 4; ) points.push(points[0]);
            return points;
        }
        function polygon(arcs) {
            return arcs.map(ring);
        }
        function geometry(o) {
            var coordinates, type = o.type;
            switch (type) {
              case "GeometryCollection":
                return {
                    type: type,
                    geometries: o.geometries.map(geometry)
                };

              case "Point":
                coordinates = point(o.coordinates);
                break;

              case "MultiPoint":
                coordinates = o.coordinates.map(point);
                break;

              case "LineString":
                coordinates = line(o.arcs);
                break;

              case "MultiLineString":
                coordinates = o.arcs.map(line);
                break;

              case "Polygon":
                coordinates = polygon(o.arcs);
                break;

              case "MultiPolygon":
                coordinates = o.arcs.map(polygon);
                break;

              default:
                return null;
            }
            return {
                type: type,
                coordinates: coordinates
            };
        }
        var transformPoint = transform(topology.transform), arcs = topology.arcs;
        return geometry(o);
    }
    function meshArcs(topology, object$$1, filter) {
        var arcs, i, n;
        if (arguments.length > 1) arcs = extractArcs(topology, object$$1, filter); else for (i = 0, 
        arcs = new Array(n = topology.arcs.length); i < n; ++i) arcs[i] = i;
        return {
            type: "MultiLineString",
            arcs: stitch(topology, arcs)
        };
    }
    function extractArcs(topology, object$$1, filter) {
        function extract0(i) {
            var j = i < 0 ? ~i : i;
            (geomsByArc[j] || (geomsByArc[j] = [])).push({
                i: i,
                g: geom
            });
        }
        function extract1(arcs) {
            arcs.forEach(extract0);
        }
        function extract2(arcs) {
            arcs.forEach(extract1);
        }
        function extract3(arcs) {
            arcs.forEach(extract2);
        }
        function geometry(o) {
            switch (geom = o, o.type) {
              case "GeometryCollection":
                o.geometries.forEach(geometry);
                break;

              case "LineString":
                extract1(o.arcs);
                break;

              case "MultiLineString":
              case "Polygon":
                extract2(o.arcs);
                break;

              case "MultiPolygon":
                extract3(o.arcs);
            }
        }
        var geom, arcs = [], geomsByArc = [];
        geometry(object$$1);
        geomsByArc.forEach(null == filter ? function(geoms) {
            arcs.push(geoms[0].i);
        } : function(geoms) {
            filter(geoms[0].g, geoms[geoms.length - 1].g) && arcs.push(geoms[0].i);
        });
        return arcs;
    }
    function planarRingArea(ring) {
        for (var a, i = -1, n = ring.length, b = ring[n - 1], area = 0; ++i < n; ) a = b, 
        b = ring[i], area += a[0] * b[1] - a[1] * b[0];
        return Math.abs(area);
    }
    function mergeArcs(topology, objects) {
        function geometry(o) {
            switch (o.type) {
              case "GeometryCollection":
                o.geometries.forEach(geometry);
                break;

              case "Polygon":
                extract(o.arcs);
                break;

              case "MultiPolygon":
                o.arcs.forEach(extract);
            }
        }
        function extract(polygon) {
            polygon.forEach(function(ring) {
                ring.forEach(function(arc) {
                    (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
                });
            });
            polygons.push(polygon);
        }
        function area(ring) {
            return planarRingArea(object(topology, {
                type: "Polygon",
                arcs: [ ring ]
            }).coordinates[0]);
        }
        var polygonsByArc = {}, polygons = [], groups = [];
        objects.forEach(geometry);
        polygons.forEach(function(polygon) {
            if (!polygon._) {
                var group = [], neighbors = [ polygon ];
                polygon._ = 1;
                groups.push(group);
                for (;polygon = neighbors.pop(); ) {
                    group.push(polygon);
                    polygon.forEach(function(ring) {
                        ring.forEach(function(arc) {
                            polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
                                if (!polygon._) {
                                    polygon._ = 1;
                                    neighbors.push(polygon);
                                }
                            });
                        });
                    });
                }
            }
        });
        polygons.forEach(function(polygon) {
            delete polygon._;
        });
        return {
            type: "MultiPolygon",
            arcs: groups.map(function(polygons) {
                var n, arcs = [];
                polygons.forEach(function(polygon) {
                    polygon.forEach(function(ring) {
                        ring.forEach(function(arc) {
                            polygonsByArc[arc < 0 ? ~arc : arc].length < 2 && arcs.push(arc);
                        });
                    });
                });
                arcs = stitch(topology, arcs);
                if ((n = arcs.length) > 1) for (var ki, t, i = 1, k = area(arcs[0]); i < n; ++i) (ki = area(arcs[i])) > k && (t = arcs[0], 
                arcs[0] = arcs[i], arcs[i] = t, k = ki);
                return arcs;
            })
        };
    }
    var identity = function(x) {
        return x;
    }, transform = function(transform) {
        if (null == transform) return identity;
        var x0, y0, kx = transform.scale[0], ky = transform.scale[1], dx = transform.translate[0], dy = transform.translate[1];
        return function(input, i) {
            i || (x0 = y0 = 0);
            var j = 2, n = input.length, output = new Array(n);
            output[0] = (x0 += input[0]) * kx + dx;
            output[1] = (y0 += input[1]) * ky + dy;
            for (;j < n; ) output[j] = input[j], ++j;
            return output;
        };
    }, bbox = function(topology) {
        function bboxPoint(p) {
            p = t(p);
            p[0] < x0 && (x0 = p[0]);
            p[0] > x1 && (x1 = p[0]);
            p[1] < y0 && (y0 = p[1]);
            p[1] > y1 && (y1 = p[1]);
        }
        function bboxGeometry(o) {
            switch (o.type) {
              case "GeometryCollection":
                o.geometries.forEach(bboxGeometry);
                break;

              case "Point":
                bboxPoint(o.coordinates);
                break;

              case "MultiPoint":
                o.coordinates.forEach(bboxPoint);
            }
        }
        var key, t = transform(topology.transform), x0 = 1 / 0, y0 = x0, x1 = -x0, y1 = -x0;
        topology.arcs.forEach(function(arc) {
            for (var p, i = -1, n = arc.length; ++i < n; ) {
                p = t(arc[i], i);
                p[0] < x0 && (x0 = p[0]);
                p[0] > x1 && (x1 = p[0]);
                p[1] < y0 && (y0 = p[1]);
                p[1] > y1 && (y1 = p[1]);
            }
        });
        for (key in topology.objects) bboxGeometry(topology.objects[key]);
        return [ x0, y0, x1, y1 ];
    }, reverse = function(array, n) {
        for (var t, j = array.length, i = j - n; i < --j; ) t = array[i], array[i++] = array[j], 
        array[j] = t;
    }, feature = function(topology, o) {
        return "GeometryCollection" === o.type ? {
            type: "FeatureCollection",
            features: o.geometries.map(function(o) {
                return feature$1(topology, o);
            })
        } : feature$1(topology, o);
    }, stitch = function(topology, arcs) {
        function ends(i) {
            var p1, arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0];
            topology.transform ? (p1 = [ 0, 0 ], arc.forEach(function(dp) {
                p1[0] += dp[0], p1[1] += dp[1];
            })) : p1 = arc[arc.length - 1];
            return i < 0 ? [ p1, p0 ] : [ p0, p1 ];
        }
        function flush(fragmentByEnd, fragmentByStart) {
            for (var k in fragmentByEnd) {
                var f = fragmentByEnd[k];
                delete fragmentByStart[f.start];
                delete f.start;
                delete f.end;
                f.forEach(function(i) {
                    stitchedArcs[i < 0 ? ~i : i] = 1;
                });
                fragments.push(f);
            }
        }
        var stitchedArcs = {}, fragmentByStart = {}, fragmentByEnd = {}, fragments = [], emptyIndex = -1;
        arcs.forEach(function(i, j) {
            var t, arc = topology.arcs[i < 0 ? ~i : i];
            arc.length < 3 && !arc[1][0] && !arc[1][1] && (t = arcs[++emptyIndex], arcs[emptyIndex] = i, 
            arcs[j] = t);
        });
        arcs.forEach(function(i) {
            var f, g, e = ends(i), start = e[0], end = e[1];
            if (f = fragmentByEnd[start]) {
                delete fragmentByEnd[f.end];
                f.push(i);
                f.end = end;
                if (g = fragmentByStart[end]) {
                    delete fragmentByStart[g.start];
                    var fg = g === f ? f : f.concat(g);
                    fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
                } else fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
            } else if (f = fragmentByStart[end]) {
                delete fragmentByStart[f.start];
                f.unshift(i);
                f.start = start;
                if (g = fragmentByEnd[start]) {
                    delete fragmentByEnd[g.end];
                    var gf = g === f ? f : g.concat(f);
                    fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
                } else fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
            } else {
                f = [ i ];
                fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
            }
        });
        flush(fragmentByEnd, fragmentByStart);
        flush(fragmentByStart, fragmentByEnd);
        arcs.forEach(function(i) {
            stitchedArcs[i < 0 ? ~i : i] || fragments.push([ i ]);
        });
        return fragments;
    }, mesh = function(topology) {
        return object(topology, meshArcs.apply(this, arguments));
    }, merge = function(topology) {
        return object(topology, mergeArcs.apply(this, arguments));
    }, bisect = function(a, x) {
        for (var lo = 0, hi = a.length; lo < hi; ) {
            var mid = lo + hi >>> 1;
            a[mid] < x ? lo = mid + 1 : hi = mid;
        }
        return lo;
    }, neighbors = function(objects) {
        function line(arcs, i) {
            arcs.forEach(function(a) {
                a < 0 && (a = ~a);
                var o = indexesByArc[a];
                o ? o.push(i) : indexesByArc[a] = [ i ];
            });
        }
        function polygon(arcs, i) {
            arcs.forEach(function(arc) {
                line(arc, i);
            });
        }
        function geometry(o, i) {
            "GeometryCollection" === o.type ? o.geometries.forEach(function(o) {
                geometry(o, i);
            }) : o.type in geometryType && geometryType[o.type](o.arcs, i);
        }
        var indexesByArc = {}, neighbors = objects.map(function() {
            return [];
        }), geometryType = {
            LineString: line,
            MultiLineString: polygon,
            Polygon: polygon,
            MultiPolygon: function(arcs, i) {
                arcs.forEach(function(arc) {
                    polygon(arc, i);
                });
            }
        };
        objects.forEach(geometry);
        for (var i in indexesByArc) for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) for (var k = j + 1; k < m; ++k) {
            var n, ij = indexes[j], ik = indexes[k];
            (n = neighbors[ij])[i = bisect(n, ik)] !== ik && n.splice(i, 0, ik);
            (n = neighbors[ik])[i = bisect(n, ij)] !== ij && n.splice(i, 0, ij);
        }
        return neighbors;
    }, untransform = function(transform) {
        if (null == transform) return identity;
        var x0, y0, kx = transform.scale[0], ky = transform.scale[1], dx = transform.translate[0], dy = transform.translate[1];
        return function(input, i) {
            i || (x0 = y0 = 0);
            var j = 2, n = input.length, output = new Array(n), x1 = Math.round((input[0] - dx) / kx), y1 = Math.round((input[1] - dy) / ky);
            output[0] = x1 - x0, x0 = x1;
            output[1] = y1 - y0, y0 = y1;
            for (;j < n; ) output[j] = input[j], ++j;
            return output;
        };
    }, quantize = function(topology, transform) {
        function quantizePoint(point) {
            return t(point);
        }
        function quantizeGeometry(input) {
            var output;
            switch (input.type) {
              case "GeometryCollection":
                output = {
                    type: "GeometryCollection",
                    geometries: input.geometries.map(quantizeGeometry)
                };
                break;

              case "Point":
                output = {
                    type: "Point",
                    coordinates: quantizePoint(input.coordinates)
                };
                break;

              case "MultiPoint":
                output = {
                    type: "MultiPoint",
                    coordinates: input.coordinates.map(quantizePoint)
                };
                break;

              default:
                return input;
            }
            null != input.id && (output.id = input.id);
            null != input.bbox && (output.bbox = input.bbox);
            null != input.properties && (output.properties = input.properties);
            return output;
        }
        function quantizeArc(input) {
            var p, i = 0, j = 1, n = input.length, output = new Array(n);
            output[0] = t(input[0], 0);
            for (;++i < n; ) ((p = t(input[i], i))[0] || p[1]) && (output[j++] = p);
            1 === j && (output[j++] = [ 0, 0 ]);
            output.length = j;
            return output;
        }
        if (topology.transform) throw new Error("already quantized");
        if (transform && transform.scale) box = topology.bbox; else {
            if (!((n = Math.floor(transform)) >= 2)) throw new Error("n must be ≥2");
            box = topology.bbox || bbox(topology);
            var n, x0 = box[0], y0 = box[1], x1 = box[2], y1 = box[3];
            transform = {
                scale: [ x1 - x0 ? (x1 - x0) / (n - 1) : 1, y1 - y0 ? (y1 - y0) / (n - 1) : 1 ],
                translate: [ x0, y0 ]
            };
        }
        var box, key, t = untransform(transform), inputs = topology.objects, outputs = {};
        for (key in inputs) outputs[key] = quantizeGeometry(inputs[key]);
        return {
            type: "Topology",
            bbox: box,
            transform: transform,
            objects: outputs,
            arcs: topology.arcs.map(quantizeArc)
        };
    };
    exports.bbox = bbox;
    exports.feature = feature;
    exports.mesh = mesh;
    exports.meshArcs = meshArcs;
    exports.merge = merge;
    exports.mergeArcs = mergeArcs;
    exports.neighbors = neighbors;
    exports.quantize = quantize;
    exports.transform = transform;
    exports.untransform = untransform;
    Object.defineProperty(exports, "__esModule", {
        value: !0
    });
});

AMapUI.weakDefine("ui/geo/DistrictExplorer/lib/distDataParser", [ "./bbIdxBuilder", "./BoundsItem", "../ext/topojson-client" ], function(bbIdxBuilder, BoundsItem, topojson) {
    function parseTopo(topo) {
        var result = {}, objects = topo.objects;
        for (var k in objects) objects.hasOwnProperty(k) && (result[k] = topojson.feature(topo, objects[k]));
        return result;
    }
    function filterSub(geoData) {
        for (var features = geoData.sub ? geoData.sub.features : [], parentProps = geoData.parent.properties, subAcroutes = (parentProps.acroutes || []).concat([ parentProps.adcode ]), i = 0, len = features.length; i < len; i++) {
            features[i].properties.subFeatureIndex = i;
            features[i].properties.acroutes = subAcroutes;
        }
    }
    function buildData(data) {
        if (!data._isBuiled) {
            bbIdxBuilder.buildIdxList(data.bbIndex);
            data.geoData = parseTopo(data.topo);
            data.geoData.sub && filterSub(data.geoData);
            var bbox = data.topo.bbox;
            data.bounds = new BoundsItem(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]);
            data.topo = null;
            data._isBuiled = !0;
        }
        return data;
    }
    return {
        buildData: buildData
    };
});

AMapUI.weakDefine("ui/geo/DistrictExplorer/lib/AreaNode", [ "lib/utils", "lib/SphericalMercator", "./Const", "./geomUtils", "./bbIdxBuilder" ], function(utils, SphericalMercator, Const, geomUtils, bbIdxBuilder) {
    function AreaNode(adcode, data, opts) {
        this.adcode = adcode;
        this._data = data;
        this._sqScaleFactor = data.scale * data.scale;
        this._opts = utils.extend({
            nearTolerance: 2
        }, opts);
        this.setNearTolerance(this._opts.nearTolerance);
    }
    var staticMethods = {
        getPropsOfFeature: function(f) {
            return f && f.properties ? f.properties : null;
        },
        getAdcodeOfFeature: function(f) {
            return f ? f.properties.adcode : null;
        },
        doesFeatureHasChildren: function(f) {
            return !!f && f.properties.childrenNum > 0;
        }
    };
    utils.extend(AreaNode, staticMethods);
    utils.extend(AreaNode.prototype, staticMethods, {
        setNearTolerance: function(t) {
            this._opts.nearTolerance = t;
            this._sqNearTolerance = t * t;
        },
        getIdealZoom: function() {
            return this._data.idealZoom;
        },
        _getEmptySubFeatureGroupItem: function(idx) {
            return {
                subFeatureIndex: idx,
                subFeature: this.getSubFeatureByIndex(idx),
                pointsIndexes: [],
                points: []
            };
        },
        groupByPosition: function(points, getPosition) {
            var i, len, groupMap = {}, outsideItem = null;
            for (i = 0, len = points.length; i < len; i++) {
                var idx = this.getLocatedSubFeatureIndex(getPosition.call(null, points[i], i));
                groupMap[idx] || (groupMap[idx] = this._getEmptySubFeatureGroupItem(idx));
                groupMap[idx].pointsIndexes.push(i);
                groupMap[idx].points.push(points[i]);
                idx < 0 && (outsideItem = groupMap[idx]);
            }
            var groupList = [];
            if (this._data.geoData.sub) for (i = 0, len = this._data.geoData.sub.features.length; i < len; i++) groupList.push(groupMap[i] || this._getEmptySubFeatureGroupItem(i));
            outsideItem && groupList.push(outsideItem);
            groupMap = null;
            return groupList;
        },
        getLocatedSubFeature: function(lngLat) {
            var fIdx = this.getLocatedSubFeatureIndex(lngLat);
            return this.getSubFeatureByIndex(fIdx);
        },
        getLocatedSubFeatureIndex: function(lngLat) {
            return this._getLocatedSubFeatureIndexByPixel(this.lngLatToPixel(lngLat, this._data.pz));
        },
        getSubFeatureByIndex: function(fIdx) {
            if (fIdx >= 0) {
                var features = this.getSubFeatures();
                return features[fIdx];
            }
            return null;
        },
        getSubFeatureByAdcode: function(adcode) {
            adcode = parseInt(adcode, 10);
            for (var features = this.getSubFeatures(), i = 0, len = features.length; i < len; i++) if (this.getAdcodeOfFeature(features[i]) === adcode) return features[i];
            return null;
        },
        _getLocatedSubFeatureIndexByPixel: function(pixel) {
            if (!this._data.geoData.sub) return -1;
            var data = this._data, bbIdx = data.bbIndex, offX = pixel[0] - bbIdx.l, offY = pixel[1] - bbIdx.t, y = Math.floor(offY / bbIdx.s), x = Math.floor(offX / bbIdx.s);
            if (x < 0 || y < 0 || y >= bbIdx.h || x >= bbIdx.w) return -1;
            var seqIdx = y * bbIdx.w + x, idxItem = bbIdx.idxList[seqIdx];
            if (!idxItem) return -1;
            var BBRFLAG = Const.BBRFLAG;
            switch (idxItem[0]) {
              case BBRFLAG.I:
                return idxItem[1];

              case BBRFLAG.S:
                bbIdxBuilder.prepareGridFeatureClip(data, x, y, idxItem[1]);
                return this._calcLocatedFeatureIndexOfSList(pixel, idxItem[1]);

              default:
                throw new Error("Unknown BBRFLAG: " + idxItem[0]);
            }
        },
        _calcNearestFeatureIndexOfSList: function(pixel, list) {
            var features = [];
            this._data.geoData.sub && (features = this._data.geoData.sub.features);
            for (var closest = {
                sq: Number.MAX_VALUE,
                idx: -1
            }, i = 0, len = list.length; i < len; i++) {
                var idxItem = list[i], feature = features[idxItem[0]], ring = idxItem[2] || feature.geometry.coordinates[idxItem[1]][0], sqDistance = geomUtils.sqClosestDistanceToPolygon(pixel, ring);
                if (sqDistance < closest.sq) {
                    closest.sq = sqDistance;
                    closest.idx = idxItem[0];
                }
            }
            return closest.sq / this._sqScaleFactor < this._sqNearTolerance ? closest.idx : -1;
        },
        _calcLocatedFeatureIndexOfSList: function(pixel, list) {
            for (var features = this._data.geoData.sub.features, i = 0, len = list.length; i < len; i++) {
                var idxItem = list[i], feature = features[idxItem[0]], ring = idxItem[2] || feature.geometry.coordinates[idxItem[1]][0];
                if (geomUtils.pointInPolygon(pixel, ring) || geomUtils.pointOnPolygon(pixel, ring)) return idxItem[0];
            }
            return this._calcNearestFeatureIndexOfSList(pixel, list);
        },
        pixelToLngLat: function(x, y) {
            return SphericalMercator.pointToLngLat([ x, y ], this._data.pz);
        },
        lngLatToPixel: function(lngLat) {
            lngLat instanceof AMap.LngLat && (lngLat = [ lngLat.getLng(), lngLat.getLat() ]);
            var pMx = SphericalMercator.lngLatToPoint(lngLat, this._data.pz);
            return [ Math.round(pMx[0]), Math.round(pMx[1]) ];
        },
        _convertRingCoordsToLngLats: function(ring) {
            for (var list = [], i = 0, len = ring.length; i < len; i++) list[i] = this.pixelToLngLat(ring[i][0], ring[i][1]);
            return list;
        },
        _convertPolygonCoordsToLngLats: function(poly) {
            for (var list = [], i = 0, len = poly.length; i < len; i++) list[i] = this._convertRingCoordsToLngLats(poly[i]);
            return list;
        },
        _convertMultiPolygonCoordsToLngLats: function(polys) {
            for (var list = [], i = 0, len = polys.length; i < len; i++) list[i] = this._convertPolygonCoordsToLngLats(polys[i]);
            return list;
        },
        _convertCoordsToLngLats: function(type, coordinates) {
            switch (type) {
              case "MultiPolygon":
                return this._convertMultiPolygonCoordsToLngLats(coordinates);

              default:
                throw new Error("Unknown type", type);
            }
        },
        _createLngLatFeature: function(f, extraProps) {
            var newNode = utils.extend({}, f);
            extraProps && utils.extend(newNode.properties, extraProps);
            newNode.geometry = utils.extend({}, newNode.geometry);
            newNode.geometry.coordinates = this._convertCoordsToLngLats(newNode.geometry.type, newNode.geometry.coordinates);
            return newNode;
        },
        getAdcode: function() {
            return this.getProps("adcode");
        },
        getName: function() {
            return this.getProps("name");
        },
        getChildrenNum: function() {
            return this.getProps("childrenNum");
        },
        getProps: function(key) {
            var props = AreaNode.getPropsOfFeature(this._data.geoData.parent);
            return props ? key ? props[key] : props : null;
        },
        getParentFeature: function() {
            var geoData = this._data.geoData;
            geoData.lngLatParent || (geoData.lngLatParent = this._createLngLatFeature(geoData.parent));
            return geoData.lngLatParent;
        },
        getParentFeatureInPixel: function() {
            return this._data.geoData.parent;
        },
        getSubFeatures: function() {
            var geoData = this._data.geoData;
            if (!geoData.sub) return [];
            if (!geoData.lngLatSubList) {
                for (var features = geoData.sub.features, newFList = [], i = 0, len = features.length; i < len; i++) newFList[i] = this._createLngLatFeature(features[i]);
                geoData.lngLatSubList = newFList;
            }
            return [].concat(geoData.lngLatSubList);
        },
        getSubFeaturesInPixel: function() {
            return this._data.geoData.sub ? [].concat(this._data.geoData.sub.features) : [];
        },
        getBounds: function() {
            var data = this._data;
            if (!data.lngLatBounds) {
                var nodeBounds = this._data.bounds;
                data.lngLatBounds = new AMap.Bounds(this.pixelToLngLat(nodeBounds.x, nodeBounds.y + nodeBounds.height), this.pixelToLngLat(nodeBounds.x + nodeBounds.width, nodeBounds.y));
            }
            return data.lngLatBounds;
        }
    });
    return AreaNode;
});

AMapUI.weakDefine("ui/geo/DistrictExplorer/main", [ "require", "lib/event", "lib/utils", "./lib/Const", "./lib/distDataParser", "./lib/AreaNode" ], function(require, EventCls, utils, Const, distDataParser, AreaNode) {
    function DistrictExplorer(opts) {
        this._opts = utils.extend({
            distDataLoc: "./assets/d_v2",
            eventSupport: !1,
            keepFeaturePolygonReference: !0,
            mouseEventNames: [ "click" ],
            mousemoveDebounceWait: -1
        }, opts);
        DistrictExplorer.__super__.constructor.call(this, this._opts);
        this._hoverFeature = null;
        this._areaNodesForLocating = null;
        this._areaNodeCache = globalAreaNodeCache;
        this._renderedPolygons = [];
        this._opts.preload && this.loadMultiAreaNodes(this._opts.preload);
        this._debouncedHandleMousemove = this._opts.mousemoveDebounceWait > 1 ? utils.debounce(this._handleMousemove, this._opts.mousemoveDebounceWait) : this._handleMousemove;
        this._opts.map && this._opts.eventSupport && this._bindMapEvents(!0);
    }
    var globalAreaNodeCache = {};
    utils.inherit(DistrictExplorer, EventCls);
    utils.extend(DistrictExplorer.prototype, {
        setAreaNodesForLocating: function(areaNodes) {
            areaNodes ? utils.isArray(areaNodes) || (areaNodes = [ areaNodes ]) : areaNodes = [];
            this._areaNodesForLocating = areaNodes || [];
        },
        getLocatedSubFeature: function(position) {
            var areaNodes = this._areaNodesForLocating;
            if (!areaNodes) return null;
            for (var i = 0, len = areaNodes.length; i < len; i++) {
                var feature = areaNodes[i].getLocatedSubFeature(position);
                if (feature) return feature;
            }
            return null;
        },
        setMap: function(map) {
            var oldMap = this._opts.map;
            if (oldMap !== map) {
                this.offMapEvents();
                this._opts.map = map;
                this._opts.map && this._opts.eventSupport && this._bindMapEvents(!0);
            }
        },
        offMapEvents: function() {
            this._bindMapEvents(!1);
        },
        _bindMapEvents: function(on) {
            for (var map = this._opts.map, action = on ? "on" : "off", mouseEventNames = this._opts.mouseEventNames, i = 0, len = mouseEventNames.length; i < len; i++) map[action](mouseEventNames[i], this._handleMouseEvent, this);
            AMap.UA.mobile || map[action]("mousemove", this._debouncedHandleMousemove, this);
        },
        _handleMouseEvent: function(e) {
            var feature = this.getLocatedSubFeature(e.lnglat);
            this.triggerWithOriginalEvent((feature ? "feature" : "outside") + utils.ucfirst(e.type), e, feature);
        },
        _handleMousemove: function(e) {
            var feature = this.getLocatedSubFeature(e.lnglat);
            this.setHoverFeature(feature, e);
            feature && this.triggerWithOriginalEvent("featureMousemove", e, feature);
        },
        setHoverFeature: function(feature, e) {
            var oldHoverFeature = this._hoverFeature;
            if (feature !== oldHoverFeature) {
                oldHoverFeature && this.triggerWithOriginalEvent("featureMouseout", e, oldHoverFeature);
                this._hoverFeature = feature;
                feature && this.triggerWithOriginalEvent("featureMouseover", e, feature, oldHoverFeature);
                this.triggerWithOriginalEvent("hoverFeatureChanged", e, feature, oldHoverFeature);
            }
        },
        _loadJson: function(src, callback) {
            var self = this;
            return require([ "json!" + src ], function(data) {
                callback && callback.call(self, null, data);
            }, function(error) {
                if (!callback) throw error;
                callback(error);
            });
        },
        _getAreaNodeDataFileName: function(adcode) {
            return "an_" + adcode + ".json";
        },
        _getAreaNodeDataSrc: function(adcode) {
            return this._opts.distDataLoc + "/" + this._getAreaNodeDataFileName(adcode);
        },
        _isAreaNodeJsonId: function(id, adcode) {
            return id.indexOf(!1) && id.indexOf(this._getAreaNodeDataFileName(adcode)) > 0;
        },
        _undefAreaNodeJson: function(adcode) {
            var id = AMapUI.findDefinedId(function(id) {
                return this._isAreaNodeJsonId(id, adcode);
            }, this);
            if (id) {
                AMapUI.require.undef(id);
                return !0;
            }
            return !1;
        },
        loadAreaTree: function(callback) {
            this._loadJson(this._opts.distDataLoc + "/area_tree.json", callback);
        },
        loadCountryNode: function(callback) {
            this.loadAreaNode(Const.ADCODES.COUNTRY, callback);
        },
        loadMultiAreaNodes: function(adcodes, callback) {
            function buildCallback(i) {
                return function(error, areaNode) {
                    if (!done) {
                        left--;
                        if (error) {
                            callback && callback(error);
                            done = !0;
                        } else {
                            results[i] = areaNode;
                            0 === left && callback && callback(null, results);
                        }
                    }
                };
            }
            if (adcodes && adcodes.length) for (var len = adcodes.length, left = len, results = [], done = !1, i = 0; i < len; i++) this.loadAreaNode(adcodes[i], callback ? buildCallback(i) : null); else callback && callback(null, []);
        },
        loadAreaNode: function(adcode, callback, thisArg, canSync) {
            thisArg = thisArg || this;
            if (this._areaNodeCache[adcode]) {
                if (callback) {
                    var areaNode = this._areaNodeCache[adcode];
                    canSync ? callback.call(thisArg, null, areaNode, !0) : setTimeout(function() {
                        callback.call(thisArg, null, areaNode);
                    }, 0);
                }
            } else this._loadJson(this._getAreaNodeDataSrc(adcode), function(err, data) {
                if (err) callback && callback.call(thisArg, err); else {
                    this._buildAreaNode(adcode, data);
                    callback && callback.call(thisArg, null, this._areaNodeCache[adcode]);
                }
            });
        },
        getLocalAreaNode: function(adcode) {
            return this._areaNodeCache[adcode] || null;
        },
        locatePosition: function(lngLat, callback, opts) {
            opts = utils.extend({
                levelLimit: 10
            }, opts);
            var parentNode = opts.parentNode;
            parentNode ? this._routeLocate(lngLat, parentNode, [], callback, opts) : this.loadCountryNode(function(err, countryNode) {
                err ? callback && callback(err) : this._routeLocate(lngLat, countryNode, [], callback, opts);
            });
        },
        _routeLocate: function(lngLat, parentNode, routes, callback, opts) {
            var subFeature = parentNode.getLocatedSubFeature(lngLat), gotChildren = !1;
            if (subFeature) {
                routes.pop();
                routes.push(parentNode.getParentFeature());
                routes.push(subFeature);
                gotChildren = parentNode.doesFeatureHasChildren(subFeature);
            }
            gotChildren && routes.length < opts.levelLimit ? this.loadAreaNode(parentNode.getAdcodeOfFeature(subFeature), function(err, subNode) {
                err ? callback && callback(err) : this._routeLocate(lngLat, subNode, routes, callback, opts);
            }) : callback && callback.call(this, null, routes.slice(0, opts.levelLimit));
        },
        _buildAreaNode: function(adcode, distData) {
            if (!this._areaNodeCache[adcode]) {
                if (!distData) throw new Error("Empty distData: " + adcode);
                var areaNode = new AreaNode(adcode, distDataParser.buildData(distData), this._opts);
                this._areaNodeCache[adcode] = areaNode;
                this._areaNodesForLocating || (this._areaNodesForLocating = [ areaNode ]);
            }
        },
        _renderMultiPolygon: function(coords, styleOptions, attchedData) {
            for (var polygons = [], i = 0, len = coords.length; i < len; i++) styleOptions && polygons.push(this._renderPolygon(coords[i], styleOptions[i] || styleOptions, attchedData));
            return polygons;
        },
        _renderPolygon: function(coords, styleOptions, attchedData) {
            if (!styleOptions) return null;
            var polygon = new AMap.Polygon(utils.extend({
                bubble: !0,
                lineJoin: "round",
                map: this._opts.map
            }, styleOptions, {
                path: coords
            }));
            attchedData && (polygon._attched = attchedData);
            this._opts.keepFeaturePolygonReference && this._renderedPolygons.push(polygon);
            return polygon;
        },
        getAdcodeOfFeaturePolygon: function(polygon) {
            return polygon._attched ? polygon._attched.adcode : null;
        },
        findFeaturePolygonsByAdcode: function(adcode) {
            var list = this._renderedPolygons, polys = [];
            adcode = parseInt(adcode, 10);
            for (var i = 0, len = list.length; i < len; i++) this.getAdcodeOfFeaturePolygon(list[i]) === adcode && polys.push(list[i]);
            return polys;
        },
        getAllFeaturePolygons: function() {
            return this._renderedPolygons;
        },
        clearFeaturePolygons: function() {
            for (var list = this._renderedPolygons, i = 0, len = list.length; i < len; i++) list[i].setMap(null);
            list.length = 0;
        },
        removeFeaturePolygonsByAdcode: function(adcode) {
            this.removeFeaturePolygons(this.findFeaturePolygonsByAdcode(adcode));
        },
        removeFeaturePolygons: function(polygons) {
            for (var list = this._renderedPolygons, i = 0, len = list.length; i < len; i++) if (polygons.indexOf(list[i]) >= 0) {
                list[i].setMap(null);
                list.splice(i, 1);
                i--;
                len--;
            }
        },
        clearAreaNodeCacheByAdcode: function(adcode) {
            var nodeCache = this._areaNodeCache;
            if (this._undefAreaNodeJson(adcode)) {
                delete nodeCache[adcode];
                return !0;
            }
            console.warn("Failed undef: ", adcode);
            return !1;
        },
        clearAreaNodeCache: function(match) {
            if (match) return this.clearAreaNodeCacheByAdcode(match);
            var nodeCache = this._areaNodeCache;
            for (var adcode in nodeCache) nodeCache.hasOwnProperty(adcode) && this.clearAreaNodeCacheByAdcode(adcode);
        },
        renderFeature: function(feature, styleOptions) {
            if (!styleOptions) return null;
            var geometry = feature.geometry;
            if (!geometry) return null;
            var coords = geometry.coordinates, attchedData = feature.properties, results = [];
            switch (geometry.type) {
              case "MultiPolygon":
                results = this._renderMultiPolygon(coords, styleOptions, attchedData);
                break;

              case "Polygon":
                results = [ this._renderPolygon(coords, styleOptions, attchedData) ];
                break;

              default:
                throw new Error("Unknow geometry: " + geometry.type);
            }
            return results;
        },
        renderSubFeatures: function(areaNode, subStyleOption) {
            for (var features = areaNode.getSubFeatures(), isSubStyleFunc = utils.isFunction(subStyleOption), results = [], i = 0, len = features.length; i < len; i++) {
                var feature = features[i];
                results.push(this.renderFeature(feature, isSubStyleFunc ? subStyleOption.call(this, feature, i) : subStyleOption));
            }
            return results;
        },
        renderParentFeature: function(areaNode, parentStyleOption) {
            return this.renderFeature(areaNode.getParentFeature(), parentStyleOption);
        }
    });
    return DistrictExplorer;
});

AMapUI.weakDefine("ui/geo/DistrictExplorer", [ "ui/geo/DistrictExplorer/main" ], function(m) {
    return m;
});