如何在Swift中制作没有交集的多边形 [英] How make polygon without intersection in Swift

查看:61
本文介绍了如何在Swift中制作没有交集的多边形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在IOS Swift和Google Map sdk中,我希望每个顶点的矩形区域都是标记.因此,我不希望在多边形中相交,如果有相交,则自动重制为矩形.我可以找到如何检测交叉点,但是没有办法重做.我怎样才能做到这一点?..请帮忙.

我想先做后做.

之前 :

之后 :

ViewController ..

 导入UIKit导入GoogleMapsclass CreateLandmarkLocationVC:UIViewController {var counterMarker:Int = 0var allMarkers:[GMSMarker] = []//您不需要修改默认的init(nibName:bundle :)方法.覆盖func loadView(){//创建一个GMSCameraPosition,告诉地图显示//在缩放级别6处协调-33.86,151.20.let camera = GMSCameraPosition.camera(withLatitude:-33.86,经度:151.20,缩放:6.0)让mapView = GMSMapView.map(withFrame:CGRect.zero,camera:camera)mapView.delegate =自我mapView.isMyLocationEnabled = true视图= mapView}}扩展名CreateLandmarkLocationVC:GMSMapViewDelegate {func mapView(_ mapView:GMSMapView,didLongPressAt坐标:CLLocationCoordinate2D){//这里的自定义逻辑如果counterMarker<4 {让标记= GMSMarker()marker.position =坐标marker.title =我长按添加了它"marker.snippet ="allMarkers.append(marker)counterMarker + = 1//创建多边形,并将其分配给地图.mapView.clear()让rect = GMSMutablePath()在allMarkers中标记{rect.add(mark.position)mark.map = mapView}让多边形= GMSPolygon(路径:矩形)Polygon.fillColor = UIColor(红色:0.25,绿色:0,蓝色:0,alpha:0.05);Polygon.strokeColor = .blackpolygon.strokeWidth = 2polygon.map = mapView}}func mapView(_ mapView:GMSMapView,didLongPressInfoWindowOf标记:GMSMarker){marker.map = nil用于allMarkers.enumerated()中的(index,cmark){如果cmark.position.latitude == marker.position.longtitude,cmark.position.longitude == marker.position.longitude {allMarkers.remove(at:index)休息;}}counterMarker-= 1mapView.clear()让rect = GMSMutablePath()在allMarkers中标记{rect.add(mark.position)mark.map = mapView}//创建多边形,并将其分配给地图.让多边形= GMSPolygon(路径:矩形)Polygon.fillColor = UIColor(红色:0.25,绿色:0,蓝色:0,alpha:0.05);Polygon.strokeColor = .blackpolygon.strokeWidth = 2polygon.map = mapView}} 

解决方案

为了解决您的问题,您应该按顺时针方向重新排列GMSMutablePath的坐标.我已经修改了您的示例,并添加了执行此任务的函数reorderMarkersClockwise(),isLess()和getCenterPointOfPoints().代码段如下

 导入UIKit导入GoogleMaps类ViewController:UIViewController {var counterMarker:Int = 0var allMarkers:[GMSMarker] = []覆盖func viewDidLoad(){super.viewDidLoad()//加载视图后进行其他任何设置,通常是从笔尖进行.}覆盖func didReceiveMemoryWarning(){super.didReceiveMemoryWarning()//处理所有可以重新创建的资源.}覆盖func loadView(){let camera = GMSCameraPosition.camera(withLatitude:-33.86,经度:151.20,缩放:6.0)让mapView = GMSMapView.map(withFrame:CGRect.zero,camera:camera)mapView.delegate =自我mapView.isMyLocationEnabled = true视图= mapView}}扩展ViewController:GMSMapViewDelegate {func mapView(_ mapView:GMSMapView,didLongPressAt坐标:CLLocationCoordinate2D){//这里的自定义逻辑如果counterMarker<4 {让标记= GMSMarker()marker.position =坐标marker.title =我长按添加了它"marker.snippet ="allMarkers.append(marker)counterMarker + = 1//创建多边形,并将其分配给地图.mapView.clear()让rect = reorderMarkersClockwise(mapView)在allMarkers中标记{mark.map = mapView}让多边形= GMSPolygon(路径:矩形)Polygon.fillColor = UIColor(红色:0.25,绿色:0,蓝色:0,alpha:0.05);Polygon.strokeColor = .blackpolygon.strokeWidth = 2polygon.map = mapView}}func mapView(_ mapView:GMSMapView,didLongPressInfoWindowOf标记:GMSMarker){marker.map = nil用于allMarkers.enumerated()中的(index,cmark){如果cmark.position.latitude == marker.position.latitude,cmark.position.longitude == marker.position.longitude {allMarkers.remove(at:index)休息;}}counterMarker-= 1mapView.clear()让rect = reorderMarkersClockwise(mapView)在allMarkers中标记{mark.map = mapView}//创建多边形,并将其分配给地图.让多边形= GMSPolygon(路径:矩形)Polygon.fillColor = UIColor(红色:0.25,绿色:0,蓝色:0,alpha:0.05);Polygon.strokeColor = .blackpolygon.strokeWidth = 2polygon.map = mapView}func reorderMarkersClockwise(_ mapView:GMSMapView)->GMSMutablePath {让rect = GMSMutablePath()如果(counterMarker> 1){让arr = allMarkers.map {$ 0.position} .sorted(by:isLess)对于arr中的pos {rect.add(pos)}} 别的 {在allMarkers中标记{rect.add(mark.position)}}返回矩形}func isLess(_ a:CLLocationCoordinate2D,_ b:CLLocationCoordinate2D)->布尔{让中心= getCenterPointOfPoints()if(a.latitude> = 0&&b; latitude< 0){返回真}否则,如果(a.latitude == 0&& b.latitude == 0){返回经度>b.经度}let det =(纬度-中心.纬度)*(纬度-中心.纬度)-(纬度-中心.纬度)*(纬度-中心.纬度)如果(det< 0){返回真} else if(det> 0){返回假}令d1 =(纬度-中心.纬度)*(纬度-中心.纬度)+(纬度-中心.经度)*(纬度-中心.经度)令d2 =(b.纬度-中心.纬度)*(b.纬度-中心.纬度)+(b.经度-中心.经度)*(b.经度-中心.经度)返回d1>d2}func getCenterPointOfPoints()->CLLocationCoordinate2D {让arr = allMarkers.map {$ 0.position}令s1:Double = arr.map {$ 0.latitude} .reduce(0,+)令s2:Double = arr.map {$ 0.longitude} .reduce(0,+)让c_lat = arr.count>0?s1/Double(arr.count):0.0让c_lng = arr.count>0?s2/Double(arr.count):0.0返回CLLocationCoordinate2D.init(纬度:c_lat,经度:c_lng)}} 

您还可以在GitHub上找到一个示例项目:

我希望这会有所帮助!

In IOS Swift and Google map sdk, I want the rectangular area each vertex is marker. So, I don't want intersection in polygon, and auto remake to rectangular if there has intersections. I can find how to detect the intersection but there's no way to remake. How can I do that?.. Please help..

I want to make before to after.

Before :

After :

ViewController..

import UIKit
import GoogleMaps

class CreateLandmarkLocationVC: UIViewController {
    var counterMarker: Int = 0
    var allMarkers:[GMSMarker] = []


    // You don't need to modify the default init(nibName:bundle:) method.

    override func loadView() {
        // Create a GMSCameraPosition that tells the map to display the
        // coordinate -33.86,151.20 at zoom level 6.

        let camera = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 6.0)
        let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)

        mapView.delegate = self
        mapView.isMyLocationEnabled = true
        view = mapView

    }
}

extension CreateLandmarkLocationVC: GMSMapViewDelegate {

    func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) {
        // Custom logic here
        if counterMarker < 4 {
            let marker = GMSMarker()
            marker.position = coordinate
            marker.title = "I added this with a long tap"
            marker.snippet = ""
            allMarkers.append(marker)
            counterMarker += 1
            // Create the polygon, and assign it to the map.
            mapView.clear()
            let rect = GMSMutablePath()
            for mark in allMarkers {
                rect.add(mark.position)
                mark.map = mapView
            }
            let polygon = GMSPolygon(path: rect)
            polygon.fillColor = UIColor(red: 0.25, green: 0, blue: 0, alpha: 0.05);
            polygon.strokeColor = .black
            polygon.strokeWidth = 2
            polygon.map = mapView

        }
    }

    func mapView(_ mapView: GMSMapView, didLongPressInfoWindowOf marker: GMSMarker) {
        marker.map = nil
        for (index, cmark) in allMarkers.enumerated() {
            if cmark.position.latitude == marker.position.latitude, cmark.position.longitude == marker.position.longitude {
                allMarkers.remove(at: index)
                break;
            }
        }
        counterMarker -= 1

        mapView.clear()
        let rect = GMSMutablePath()
        for mark in allMarkers {
            rect.add(mark.position)
            mark.map = mapView
        }

        // Create the polygon, and assign it to the map.
        let polygon = GMSPolygon(path: rect)
        polygon.fillColor = UIColor(red: 0.25, green: 0, blue: 0, alpha: 0.05);
        polygon.strokeColor = .black
        polygon.strokeWidth = 2
        polygon.map = mapView
    }
}

解决方案

In order to solve your issue you should reorder coordinates of GMSMutablePath in clockwise direction. I have modified your example and added functions reorderMarkersClockwise(), isLess() and getCenterPointOfPoints() that do this task. The code snippet is the following

import UIKit
import GoogleMaps

class ViewController: UIViewController {
    var counterMarker: Int = 0
    var allMarkers:[GMSMarker] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func loadView() {
        let camera = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 6.0)
        let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)

        mapView.delegate = self
        mapView.isMyLocationEnabled = true
        view = mapView
    }
}

extension ViewController: GMSMapViewDelegate {

    func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) {
        // Custom logic here
        if counterMarker < 4 {
            let marker = GMSMarker()
            marker.position = coordinate
            marker.title = "I added this with a long tap"
            marker.snippet = ""
            allMarkers.append(marker)
            counterMarker += 1
            // Create the polygon, and assign it to the map.
            mapView.clear()
            let rect = reorderMarkersClockwise(mapView)
            for mark in allMarkers {
                mark.map = mapView
            }
            let polygon = GMSPolygon(path: rect)
            polygon.fillColor = UIColor(red: 0.25, green: 0, blue: 0, alpha: 0.05);
            polygon.strokeColor = .black
            polygon.strokeWidth = 2
            polygon.map = mapView

        }
    }

    func mapView(_ mapView: GMSMapView, didLongPressInfoWindowOf marker: GMSMarker) {
        marker.map = nil
        for (index, cmark) in allMarkers.enumerated() {
            if cmark.position.latitude == marker.position.latitude, cmark.position.longitude == marker.position.longitude {
                allMarkers.remove(at: index)
                break;
            }
        }
        counterMarker -= 1

        mapView.clear()
        let rect = reorderMarkersClockwise(mapView)
        for mark in allMarkers {
            mark.map = mapView
        }

        // Create the polygon, and assign it to the map.
        let polygon = GMSPolygon(path: rect)
        polygon.fillColor = UIColor(red: 0.25, green: 0, blue: 0, alpha: 0.05);
        polygon.strokeColor = .black
        polygon.strokeWidth = 2
        polygon.map = mapView
    }

    func reorderMarkersClockwise(_ mapView: GMSMapView) -> GMSMutablePath {
        let rect = GMSMutablePath()
        if (counterMarker > 1) {
            let arr = allMarkers.map{$0.position}.sorted(by: isLess)
            for pos in arr {
                rect.add(pos)
            }
        } else {
            for mark in allMarkers {
                rect.add(mark.position)
            }
        }
        return rect
    }

    func isLess(_ a: CLLocationCoordinate2D, _ b: CLLocationCoordinate2D) -> Bool {
        let center = getCenterPointOfPoints()

        if (a.latitude >= 0 && b.latitude < 0) {
            return true
        } else if (a.latitude == 0 && b.latitude == 0) {
            return a.longitude > b.longitude
        }

        let det = (a.latitude - center.latitude) * (b.longitude - center.longitude) - (b.latitude - center.latitude) * (a.longitude - center.longitude)
        if (det < 0) {
            return true
        } else if (det > 0) {
            return false
        }

        let d1 = (a.latitude - center.latitude) * (a.latitude - center.latitude) + (a.longitude - center.longitude) * (a.longitude - center.longitude)
        let d2 = (b.latitude - center.latitude) * (b.latitude - center.latitude) + (b.longitude - center.longitude) * (b.longitude - center.longitude)
        return d1 > d2
    }

    func getCenterPointOfPoints() -> CLLocationCoordinate2D {
        let arr = allMarkers.map {$0.position}
        let s1: Double = arr.map{$0.latitude}.reduce(0, +)
        let s2: Double = arr.map{$0.longitude}.reduce(0, +)
        let c_lat = arr.count > 0 ? s1 / Double(arr.count) : 0.0
        let c_lng = arr.count > 0 ? s2 / Double(arr.count) : 0.0
        return CLLocationCoordinate2D.init(latitude: c_lat, longitude: c_lng)
    }
}

You can also find a sample project on GitHub: https://github.com/xomena-so/so50679742. Use your API key to run the sample project.

I hope this helps!

这篇关于如何在Swift中制作没有交集的多边形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆