ArcGIS For Android 利用线对面进行分割
来源:互联网 发布:mac电脑excel内存不足 编辑:程序博客网 时间:2024/05/24 06:41
需求是要将一个面用线将其分割成两块或多块的面。这个面包括多路径面的极端情况。
在ArcGIS For Android提供的API中 GeometryEngine工具类中未有Segment这个方法,在官网查阅中发现在最新的100.0.0版本中是有这个方法的,但是项目中使用的是10.2.8的版本,Eris在这两个版本变化很大,要换SDK十分麻烦,要更换和地图有关的所有地方,所以只能自己动手去写这个分割逻辑。
具体代码
private void previousSegmentation(Geometry gonGeo, Geometry lineGeo) { // 这个面的集合用来做遍历 List<Geometry> gonGraphics = new ArrayList<Geometry>(); // 取线的最后一个点 判断是否穿过面 MultiPath multiPath = (MultiPath) lineGeo; MultiPath multiPathGon = (MultiPath) gonGeo; boolean isIsland = false; Point pointLast = multiPath.getPoint(multiPath.getPointCount() - 1); Point pointFirst = multiPath.getPoint(0); // 判断分割首要条件为线与面相交,并且线的第一个点与最后一个点不和面相交 if (!GeometryEngine.intersects(gonGeo, pointFirst, mMapView.getSpatialReference()) && !GeometryEngine.intersects(gonGeo, pointLast, mMapView.getSpatialReference()) && GeometryEngine.intersects(gonGeo, lineGeo, mMapView.getSpatialReference()) ) { // 遍历多路径 生成面集合 SegmentIterator segmentIterator = multiPathGon.querySegmentIterator(); while (segmentIterator.nextPath()) { Polygon polygonPath = new Polygon(); while (segmentIterator.hasNextSegment()) { polygonPath.addSegment(segmentIterator.nextSegment(), false); } polygonPath.removePoint(polygonPath.getPointCount() - 1); gonGraphics.add(polygonPath); } if (gonGraphics.size() > 1) { // 对自身集合遍历 判断是否是环岛面 for (int i = 0; i < gonGraphics.size(); i++) { for (int j = 0; j < gonGraphics.size(); j++) { if (i != j && GeometryEngine.contains(gonGraphics.get(i), gonGraphics.get(j), mMapView.getSpatialReference())) { isIsland = true; break; } } } } if (isIsland) { // 如果是环岛面 List<List<Geometry>> doubleGeo = new ArrayList<List<Geometry>>(); // 第一步 区分大面和小面 // 对面集合进行按面积大小的冒泡排序 for (int k = 0; k < gonGraphics.size(); k++) { for (int z = 0; z < gonGraphics.size() - 1 - k; z++) { double index = Math.abs(gonGraphics.get(z).calculateArea2D()); double index1 = Math.abs(gonGraphics.get(z + 1).calculateArea2D()); if (index < index1) { gonGraphics.add(z, gonGraphics.get(z + 1)); gonGraphics.remove(z + 2); } } } // 对面进行分组 for (int i = 0; i < gonGraphics.size(); i++) { List<Geometry> singleGeo = new ArrayList<Geometry>(); if (gonGraphics.get(i).calculateArea2D() > 0) {// 环岛小面的面积是负数 for (int j = 0; j < gonGraphics.size(); j++) { if (i != j && GeometryEngine.contains(gonGraphics.get(i), gonGraphics.get(j), mMapView.getSpatialReference())) { if (singleGeo.isEmpty()) {// 如果暂时没有面 则是未放入大面 singleGeo.add(gonGraphics.get(i));// 取到大面 } singleGeo.add(gonGraphics.get(j));// 取到被包含的小面 } } if (singleGeo.isEmpty()) {// 是空的情况 就是单一的普通的面 singleGeo.add(gonGraphics.get(i)); }// 不是空的情况 就是有环岛的面 doubleGeo.add(singleGeo); } } // 存放结果的集合 List<Geometry> result = new ArrayList<Geometry>(); for (int a = 0; a < doubleGeo.size(); a++) { List<Geometry> smallGeo = new ArrayList<Geometry>(); List<Geometry> geometries = doubleGeo.get(a); Geometry bigGeo = new Polygon(); for (int i = 0; i < geometries.size(); i++) { if (i == 0) { bigGeo = geometries.get(i);// 取到大面 } else { smallGeo.add(geometries.get(i));// 加入小面 } } // 第二步 大面作分割 List<Geometry> bigGeos = new ArrayList<Geometry>(); bigGeos.add(bigGeo); bigGeos = segmentation(bigGeo, lineGeo, bigGeos); // 第三步 小面作分割 List<List<Geometry>> smallData = new ArrayList<List<Geometry>>(); for (int i = 0; i < smallGeo.size(); i++) { List<Geometry> smallGeos = new ArrayList<Geometry>();// 存储一个小面分割后的面集合 smallGeos.add(smallGeo.get(i));// 加入当前需要被分割的小面 smallGeos = segmentation(smallGeo.get(i), lineGeo, smallGeos);// 获取分割后的结果 smallData.add(smallGeos); } // 第四步 大面和小面的集合作差 for (int i = 0; i < bigGeos.size(); i++) { Geometry big = bigGeos.get(i); for (int j = 0; j < smallData.size(); j++) { // 循环小面的二维集合 for (int k = 0; k < smallData.get(j).size(); k++) {// 遍历小面的一个集合的面 big = GeometryEngine.difference(big, smallData.get(j).get(k), mMapView.getSpatialReference()); } } // 一个大面遍历完所有小面后 加入结果集合 if (((MultiPath) big).getPointCount() != 0) {// 判断是否是空图形 result.add(big); } } } segmentationOver(result); } else { List<Geometry> segmentation = segmentation(gonGeo, lineGeo, gonGraphics); // 分割操作完成后 segmentationOver(segmentation); } } else { ToastUtil.showShort(this, "需要画一条穿过面的线"); editGraphicsLayer.removeGraphic(graphicsSelected.get(1).getUid()); highGraphicsLayer.removeAll(); graphicsSelected.clear(); allDisSelector(); }}/** * 分割操作 * * @param gonGeo 传入需要分割的面 * @param lineGeo 传入画出的线 * @param gonGraphics 存有需要分割的面的集合 用于返回分割完后的面集 */private List<Geometry> segmentation(Geometry gonGeo, Geometry lineGeo, List<Geometry> gonGraphics) { // 第一次相交操作 取得相交之后的线段 Geometry intersect = GeometryEngine.intersect(gonGeo, lineGeo, mMapView.getSpatialReference()); MultiPath intersectMulti = (MultiPath) intersect; // 线的路径 for (int i = 0; i < intersectMulti.getPathCount(); i++) { int pathStart = intersectMulti.getPathStart(i); int pathEnd = intersectMulti.getPathEnd(i); Polyline polyline = new Polyline(); // 完成一个路径的遍历 for (int j = pathStart; j < pathEnd - 1; j++) { Line line = new Line(); line.setStart(intersectMulti.getPoint(j)); line.setEnd(intersectMulti.getPoint(j + 1)); polyline.addSegment(line, false); } // 拿路径去和面集合遍历 List<Integer> indexList = new ArrayList<Integer>(); List<Geometry> segmentationList = new ArrayList<Geometry>(); for (int j = 0; j < gonGraphics.size(); j++) { if (GeometryEngine.intersects(gonGraphics.get(j), polyline, mMapView.getSpatialReference())) { Geometry intersectLine = GeometryEngine.intersect(gonGraphics.get(j), polyline, mMapView.getSpatialReference()); // 分割 if (((MultiPath) intersectLine).getPointCount() >= 2) { segmentationList.addAll(CalculateUtil.segmentation(gonGraphics.get(j), intersectLine, mMapView)); // 这个面被处理过后 就记录下标 indexList.add(j); } } } // 加入本次处理后的两个面 gonGraphics.addAll(segmentationList); // 处理过的面的下标 去掉 for (int j = 0; j < indexList.size(); j++) { gonGraphics.remove(indexList.get(indexList.size() - j - 1).intValue()); } } return gonGraphics;}
最主要的方法:
public static List<Geometry> segmentation(Geometry gonGeo, Geometry intersect,MapView mapView) { // 获得路径 MultiPath gonMulti = (MultiPath) gonGeo; MultiPath lineMulti = (MultiPath) intersect; Polygon polygonFirst = new Polygon(); Polygon polygonSecond = new Polygon(); int start = 0; int end = 0; // 线的顺序和面的顺序是否反向 boolean isReverse = false; // 记录交点所在的下标 int[] index = new int[2]; int count = 0; // 用交点去遍历面的线 取得 各个交点所在的线的下标 for (int j = 0; j < lineMulti.getPointCount(); j++) { Point point = lineMulti.getPoint(j); for (int i = 0; i < gonMulti.getPointCount(); i++) { Point pointFirst = gonMulti.getPoint(i); Point pointSecond; if (i + 1 == gonMulti.getPointCount()) { pointSecond = gonMulti.getPoint(0); } else { pointSecond = gonMulti.getPoint(i + 1); } Line lineInGon = new Line(); lineInGon.setStart(pointFirst); lineInGon.setEnd(pointSecond); // 面的线 Polyline polyline = new Polyline(); polyline.addSegment(lineInGon, false); if (GeometryEngine.intersects(point, polyline, mapView.getSpatialReference())) { if(count<2){ index[count] = i; count++; } } } } // 取到交点下标后 排序 if (index[0] < index[1]) { start = index[0]; end = index[1]; isReverse = false; } else if (index[0] > index[1]) { start = index[1]; end = index[0]; isReverse = true; } else if (index[0] == index[1]) { start = index[0]; end = index[1]; } for (int i = 0; i < gonMulti.getPointCount(); i++) { if (start == end) { // 交点在同一个线上 if (i != start) { Line line = new Line(); line.setStart(gonMulti.getPoint(i)); if (i + 1 == gonMulti.getPointCount()) { line.setEnd(gonMulti.getPoint(0)); } else { line.setEnd(gonMulti.getPoint(i + 1)); } polygonFirst.addSegment(line, false); } if (i == start) { double distance1 = GeometryEngine.distance(gonMulti.getPoint(i), lineMulti.getPoint(0), mapView.getSpatialReference()); double distance2 = GeometryEngine.distance(gonMulti.getPoint(i), lineMulti.getPoint(lineMulti.getPointCount() - 1), mapView.getSpatialReference()); // 判断是否反向 isReverse = distance1 > distance2; // 第一个面的点 Line line = new Line(); if (isReverse) { line.setStart(gonMulti.getPoint(i)); line.setEnd(lineMulti.getPoint(lineMulti.getPointCount() - 1)); } else { line.setStart(gonMulti.getPoint(i)); line.setEnd(lineMulti.getPoint(0)); } polygonFirst.addSegment(line, false); // 加入面中的线段 if (isReverse) { for (int k = 0; k < lineMulti.getPointCount() - 1; k++) { Line lineFirst = new Line(); lineFirst.setStart(lineMulti.getPoint(lineMulti.getPointCount() - k - 1)); lineFirst.setEnd(lineMulti.getPoint(lineMulti.getPointCount() - k - 2)); polygonFirst.addSegment(lineFirst, false); } } else { for (int k = 0; k < lineMulti.getPointCount() - 1; k++) { Line lineFirst = new Line(); lineFirst.setStart(lineMulti.getPoint(k)); lineFirst.setEnd(lineMulti.getPoint(k + 1)); polygonFirst.addSegment(lineFirst, false); } } // 加入穿过之后的线 Line lineAfter = new Line(); if (i + 1 == gonMulti.getPointCount()) { if (isReverse) { lineAfter.setStart(lineMulti.getPoint(0)); lineAfter.setEnd(gonMulti.getPoint(0)); } else { lineAfter.setStart(lineMulti.getPoint(lineMulti.getPointCount() - 1)); lineAfter.setEnd(gonMulti.getPoint(0)); } } else { if (isReverse) { lineAfter.setStart(lineMulti.getPoint(0)); lineAfter.setEnd(gonMulti.getPoint(i + 1)); } else { lineAfter.setStart(lineMulti.getPoint(lineMulti.getPointCount() - 1)); lineAfter.setEnd(gonMulti.getPoint(i + 1)); } } polygonFirst.addSegment(lineAfter, false); // 第二个面的闭合 Line lineSecond = new Line(); lineSecond.setStart(lineMulti.getPoint(lineMulti.getPointCount() - 1)); lineSecond.setEnd(lineMulti.getPoint(0)); polygonSecond.addSegment(lineSecond, false); for (int k = 0; k < lineMulti.getPointCount() - 1; k++) { Line line1 = new Line(); line1.setStart(lineMulti.getPoint(k)); line1.setEnd(lineMulti.getPoint(k + 1)); polygonSecond.addSegment(line1, false); } } } else { // 交点不在同一个线上 if (i < start) { // 小于第一个交点的点连接至第一个交点 Line line = new Line(); line.setStart(gonMulti.getPoint(i)); line.setEnd(gonMulti.getPoint(i + 1)); polygonFirst.addSegment(line, false); } if (i == start) { // 等于则连接第一个交点 这个要加三个路径 Line line = new Line(); if (isReverse) { line.setStart(gonMulti.getPoint(i)); line.setEnd(lineMulti.getPoint(lineMulti.getPointCount() - 1)); } else { line.setStart(gonMulti.getPoint(i)); line.setEnd(lineMulti.getPoint(0)); } polygonFirst.addSegment(line, false); // 加入面中的线段 if (isReverse) { for (int k = 0; k < lineMulti.getPointCount() - 1; k++) { Line lineFirst = new Line(); lineFirst.setStart(lineMulti.getPoint(lineMulti.getPointCount() - k - 1)); lineFirst.setEnd(lineMulti.getPoint(lineMulti.getPointCount() - k - 2)); polygonFirst.addSegment(lineFirst, false); } } else { for (int k = 0; k < lineMulti.getPointCount() - 1; k++) { Line lineFirst = new Line(); lineFirst.setStart(lineMulti.getPoint(k)); lineFirst.setEnd(lineMulti.getPoint(k + 1)); polygonFirst.addSegment(lineFirst, false); } } // 第二个面加入 Line lineSecond = new Line(); if (isReverse) { lineSecond.setStart(lineMulti.getPoint(lineMulti.getPointCount() - 1)); lineSecond.setEnd(gonMulti.getPoint(i + 1)); } else { lineSecond.setStart(lineMulti.getPoint(0)); lineSecond.setEnd(gonMulti.getPoint(i + 1)); } polygonSecond.addSegment(lineSecond, false); } if (i > start && i < end) { // 在两个交点之间的时候 Line line = new Line(); line.setStart(gonMulti.getPoint(i)); line.setEnd(gonMulti.getPoint(i + 1)); polygonSecond.addSegment(line, false); } if (i == end) { Line line = new Line(); line.setStart(gonMulti.getPoint(i)); if (isReverse) { line.setEnd(lineMulti.getPoint(0)); } else { line.setEnd(lineMulti.getPoint(lineMulti.getPointCount() - 1)); } polygonSecond.addSegment(line, false); // 反向加入面中的线 if (isReverse) { for (int k = 0; k < lineMulti.getPointCount() - 1; k++) { Line lineSecond = new Line(); lineSecond.setStart(lineMulti.getPoint(k)); lineSecond.setEnd(lineMulti.getPoint(k + 1)); polygonSecond.addSegment(lineSecond, false); } } else { for (int k = 0; k < lineMulti.getPointCount() - 1; k++) { Line lineSecond = new Line(); lineSecond.setStart(lineMulti.getPoint(lineMulti.getPointCount() - k - 1)); lineSecond.setEnd(lineMulti.getPoint(lineMulti.getPointCount() - k - 2)); polygonSecond.addSegment(lineSecond, false); } } // 第一个面的线 Line lineFirst = new Line(); if (isReverse) { lineFirst.setStart(lineMulti.getPoint(0)); } else { lineFirst.setStart(lineMulti.getPoint(lineMulti.getPointCount() - 1)); } if (i + 1 == gonMulti.getPointCount()) { lineFirst.setEnd(gonMulti.getPoint(0)); } else { lineFirst.setEnd(gonMulti.getPoint(i + 1)); } polygonFirst.addSegment(lineFirst, false); } if (i > end) { // 这里完成第一个面的路径 Line line = new Line(); line.setStart(gonMulti.getPoint(i)); if (i + 1 == gonMulti.getPointCount()) { // 超出下标则到0点去 line.setEnd(gonMulti.getPoint(0)); } else { line.setEnd(gonMulti.getPoint(i + 1)); } polygonFirst.addSegment(line, false); } } } polygonFirst.removePoint(polygonFirst.getPointCount() - 1); polygonSecond.removePoint(polygonSecond.getPointCount() - 1); List<Geometry> gonLists = new ArrayList<Geometry>(); gonLists.add(polygonFirst); gonLists.add(polygonSecond); return gonLists;}
这个是分割完的处理工作
private void segmentationOver(List<Geometry> gonGraphics) { editGraphicsLayer.removeGraphic(graphicsSelected.get(0).getUid()); editGraphicsLayer.removeGraphic(graphicsSelected.get(1).getUid()); highGraphicsLayer.removeAll(); graphicsSelected.clear(); allDisSelector();}
editGraphicsLayer 是当前编辑的图层对象.
highGraphicsLayer 是用来高亮的图层对象.
allDisSelector 是我用来取消要素高亮的方法.
难点主要是在于点集是有顺序的,需要判断线切入面的交点顺序和原来面的点集顺序是是否是相同的,
这个判断在segmentation()这个方法中完成。
阅读全文
1 0
- ArcGIS For Android 利用线对面进行分割
- ArcGIS教程:利用分割工具按间隔或面积对值进行分组
- ArcGIS for Android利用LocalTiledLayer 打开离线地图
- 使用Arcgis for Android进行路径分析的总体思路
- 用arcgis根据字段进行分割数据
- [arcgis for android]arcgis for android 定位
- 利用FFMPEG进行视频分割
- ArcGIS for Android
- arcgis for android 学习
- ArcGis for Android定位
- ARCGIS for android
- 说说arcGIS for Android
- ArcGis for Android 开发
- arcgis for android 图例
- ArcGis for android
- ArcGis for android
- arcgis-for-android 学习指南
- Arcgis for Android:Debug
- Referenced file contains errors (http://mybatis.org/dtd/mybatis-3-mapper.dtd). For more informatio
- Word Break
- 各类学习网址
- [LeetCode] 93. Restore IP Addresses
- 计蒜客————单独的数字
- ArcGIS For Android 利用线对面进行分割
- 剑指offer题解C++【2】
- 左偏树
- 伸展树
- jOrgChart树形图插件
- 【HTML 基础】05 表格
- hdu 2476 刷墙
- XPath
- CentOS7安装MySql遇到的问题