【问题标题】:Drawing a confidence ellipse on top of a scatter plot在散点图上绘制置信椭圆
【发布时间】:2016-09-21 13:12:31
【问题描述】:

我目前正在开发一个使用 CorePlot 库(2.1 版)绘制散点图的 iOS 应用程序。我的散点图画得很好,下一步我想在图的顶部画一个半透明的置信椭圆。我编写了一个类来计算椭圆的主轴和次轴以及所需的旋转角度。我的 ConfidenceEllipse 类实现了一个 getPath() 方法,该方法返回一个表示要绘制的椭圆的 CGPath。

func getPath() -> CGPath
{
var ellipse: CGPath

var transform = CGAffineTransformIdentity
transform = CGAffineTransformTranslate (transform, CGFloat(-self.meanX), CGFloat(-self.meanY))
transform = CGAffineTransformRotate (transform, CGFloat(self.angle))
transform = CGAffineTransformTranslate (transform, CGFloat(self.meanX), CGFloat(self.meanY))

ellipse = CGPathCreateWithEllipseInRect(CGRectMake (CGFloat(-self.mainHalfAxis), CGFloat(-self.minorHalfAxis), CGFloat(2 * self.mainHalfAxis), CGFloat(2 * self.minorHalfAxis)),&transform)

return ellipse
}

在网上搜索了一段时间后,似乎注释是要走的路,所以我尝试了这个:

let graph     = hostView.hostedGraph!
let space     = graph.defaultPlotSpace    
let ellipse = ConfidenceEllipse(chiSquare: 5.991)
ellipse.analyze(self.samples)

let annotation = CPTPlotSpaceAnnotation (plotSpace: space!, anchorPlotPoint: [0,0])
let overlay = CPTBorderedLayer (frame: graph.frame)
overlay.outerBorderPath = ellipse.getPath()

let fillColor = CPTColor.yellowColor()
overlay.fill = CPTFill (color: fillColor)

annotation.contentLayer = overlay
annotation.contentLayer?.opacity = 0.5
graph.addAnnotation(annotation)

这样做,会给我以下 Screenshot 如您所见,叠加层占据了整个框架的大小,考虑到我在创建 CPTBorderedLayer 对象时传递了框架尺寸这一事实,这似乎是合乎逻辑的。我也尝试将构造函数留空,但覆盖层根本不显示。所以我想知道,这里有什么我想念的吗?

【问题讨论】:

    标签: ios swift core-plot


    【解决方案1】:

    您需要缩放椭圆以匹配绘图。使用绘图区域bounds 作为注释层的框架,并将注释附加到绘图区域。在 x 和 y 方向上缩放椭圆,以匹配绘图空间使用的变换,以适应绘图区域中的绘图。

    编辑: 在研究了边界层是如何工作的之后,我意识到我上面的建议是行不通的。 CPTBorderedLayer 会在图层边界发生变化时自动设置outerBorderPath。与其尝试影响图层边界,不如将椭圆绘制到图像中并将其用作有边界图层的fill。您应该调整图层的大小,使椭圆正好适合其中。

    【讨论】:

    • 你说得对,我忘了缩放椭圆。我试图用绘图区域和椭圆的边界来初始化边界注释,后来缩放边界注释,使其完全覆盖散点图上的点区域,但不幸的是椭圆仍然没有显示。注释仍显示为矩形。你认为我设置 outerBorderPath 是罪魁祸首吗?阅读以下帖子stackoverflow.com/questions/11588862/…后,我想到了这一点。
    【解决方案2】:

    在未能让注释正常工作后,我决定走另一条路。我的最终解决方案是用第二个散点图覆盖我的原始散点图,它只包含一个数据点,即我的置信椭圆的中心。这是代码

        func drawConfidenceEllipse () {
    
        let graph     = hostView.hostedGraph!
        let plotSpace = graph.defaultPlotSpace as! CPTXYPlotSpace
    
        let scaleX = (graph.bounds.size.width - graph.paddingLeft - graph.paddingRight) / CGFloat(plotSpace.xRange.lengthDouble)
        let scaleY = (graph.bounds.size.height - graph.paddingTop - graph.paddingBottom) / CGFloat(plotSpace.yRange.lengthDouble)
    
        let analysis = ConfidenceEllipse(chiSquare: 5.991)
        analysis.analyze(self.samples)
        let unscaledPath = analysis.getPath()
    
        let bounds = CGPathGetBoundingBox(unscaledPath)
    
        var scaler = CGAffineTransformIdentity
        scaler = CGAffineTransformScale (scaler, scaleX, scaleY)
        scaler = CGAffineTransformTranslate (scaler, CGFloat (-bounds.origin.x), CGFloat (-bounds.origin.y))
        let scaledPath   = CGPathCreateCopyByTransformingPath (unscaledPath, &scaler)
        let scaledBounds = CGPathGetPathBoundingBox(scaledPath)
    
        let symbol = CPTPlotSymbol ()
        symbol.symbolType = CPTPlotSymbolType.Custom
        symbol.customSymbolPath = scaledPath
        symbol.fill = CPTFill (color: CPTColor.yellowColor().colorWithAlphaComponent(0.25))
        symbol.size = CGSize (width: scaledBounds.size.width, height: scaledBounds.size.height)
    
        let lineStyle = CPTMutableLineStyle()
        lineStyle.lineWidth = 1
        lineStyle.lineColor = CPTColor.yellowColor()
    
        symbol.lineStyle = lineStyle
    
        let ellipse = CPTScatterPlot (frame: hostView.frame)
        ellipse.title = "Confidence Ellipse"
        ellipse.delegate = self
        ellipse.dataSource = self
        ellipse.plotSymbol = symbol
        ellipse.dataLineStyle = nil
    
        graph.addPlot(ellipse)
    

    }

    这是最终结果的截图:

    95% Confidence Ellipse on top of scatter plot

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-11
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多