Swift CoreGraphics UIBezierPath无法正确填充内部

时间:2018-06-22 17:48:24

标签: swift core-graphics uibezierpath topojson

我试图绘制国家/地区并为内部填充某种颜色。我的数据源是一个TopoJSON文件,简而言之,它是由引用弧形数组以创建形状的形状组成的。我将其转换为paths数组,然后进行迭代以绘制国家/地区。如下面的屏幕快照所示,我正在绘制国家(阿富汗)轮廓的正确线条。

Afghanistan Outline

但是,当我尝试使用path.fill()时,最终得到以下结果。请注意,黑线是正确的,但颜色会随意地在内部和外部分布。

Afghanistan filled

代码

var mapRegion = MapRegion()
var path = mapRegion.createPath()
var origin: CGPoint = .zero

geometry.paths
    .enumerated()
    .forEach { (geoIndex, shape) in

        shape
            .enumerated()
            .forEach { (shapeIndex, coord) in

                guard let coordPoint = coord.double else { return }
                let values = coordinatesToGraphics(x: coordPoint.x, y: coordPoint.y)
                let point = CGPoint(x: values.x, y: values.y)

                if origin == .zero {
                    origin = point
                }

                // Shape is about to be closed
                if shapeIndex != 0 && path.contains(point) {

                    // Close, save path (2)
                    path.addLine(to: origin)
                    // (3) path.close()
                    mapRegion.savePath()

                    // Add to map, reset process
                    canvas.layer.addSublayer(mapRegion)
                    mapRegions.append(mapRegion)
                    mapRegion = MapRegion()
                    path = mapRegion.createPath()

                 }

                 else {
                     if shapeIndex == 0 {
                         path.move(to: point)
                     } else {
                         path.addLine(to: point)
                     }
                 }



             }

}

我已经尝试过彻底弄乱usesEvenOddFillRulefurther reading),但没有任何变化。我发现上述注释(1)有助于解决绘制边界不应该绘制的边界的问题。 (2)中的函数savePath()运行setStroke()stroke()setFill()fill()函数。

更新path.close()在形状的左下角(而不是第一次开始绘制的左上角)处绘制一条封闭路径的线。该函数关闭“最近添加的子路径”,但是如何定义子路径?

我不能确定问题是我的逻辑还是某些CoreGraphics技巧。我收集了一些路径,需要将它们组合在一起并视为一条路径,我相信我正在这样做。我已经看过数据点,一个弧的末尾到下一个弧的末尾是相同的。我打印了我缝合在一起的路径,基本上move(to:)是同一点,所以当我addLine(to:)时没有重复,看着模拟器给区域着色的方式,我首先猜测可能是各个弧被视为形状,但在此示例中只有6条弧线,还有更多的内外颜色开关。

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

事实证明,使用path.move(to:)UIBezierPath()内创建一个子路径,填充算法似乎将其视为单独的多个路径(source发现)。解决的办法是删除多余的不必要的move(to:)调用。以下是工作代码和满意的结果!谢谢!

var mapRegion = MapRegion()
var path = mapRegion.createPath()
path.move(to: .zero)
var pointsDictionary: [String: Bool] = [:]

geometry.paths
  .enumerated()
  .forEach { (geoIndex, shape) in

      shape
          .enumerated()
          .forEach { (shapeIndex, coord) in

              guard let coordPoint = coord.double else { return }
              let values = coordinatesToGraphics(x: coordPoint.x, y: coordPoint.y)
              let point = CGPoint(x: values.x, y: values.y)

              // Move to start
              if path.currentPoint == .zero {
                  path.move(to: point)
              }

              if shapeIndex != 0 {

                  // Close shape
                  if pointsDictionary[point.debugDescription] ?? false {

                      // Close path, set colors, save
                      mapRegion.save(path)
                      regionDrawer.drawPath(of: mapRegion)

                      // Reset process
                      canvas.layer.addSublayer(mapRegion)
                      mapRegions.append(mapRegion)
                      mapRegion = MapRegion()
                      path = mapRegion.createPath()
                      pointsDictionary = [:]

                  }

                  // Add to shape
                  else {
                      path.addLine(to: point)
                  }

              }

      }

}

enter image description here