2016-09-21 4 views
0

В настоящее время я работаю над приложением iOS, где я использую библиотеку CorePlot (версия 2.1), чтобы нарисовать график рассеяния. Мой график рассеяния рисует хорошо, и на следующем шаге я хотел бы нарисовать полупрозрачный эллипс доверия поверх сюжета. Я написал класс, вычисляющий основную и вспомогательную ось и необходимый угол поворота моего эллипса. Мой класс 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. Я также попробовал оставить конструктор пустым, но затем наложение вообще не отображается. Поэтому мне интересно, есть ли что-то, чего я здесь не хватает?

ответ

0

Вам необходимо масштабировать эллипс в соответствии с графиком. Используйте область графика bounds для рамки слоя аннотации и приложите аннотацию к области графика. Масштабируйте эллипс в направлениях x и y, чтобы соответствовать преобразованию, используемому пространством графика, чтобы соответствовать графикам в области графика.

Редактировать: Изучив, как работают граничные слои, я понял, что мое предложение выше не будет работать. CPTBorderedLayer автоматически устанавливает outerBorderPath всякий раз, когда изменяется граница слоя. Вместо того, чтобы пытаться повлиять на границу слоя, нарисуйте эллипс в изображении и используйте его как fill для пограничного слоя. Вы должны размер слоя, чтобы эллипс просто вписывался внутрь.

+0

Вы правы, я забыл масштабирование эллипса. Я попытался инициализировать пограничную аннотацию как границами области графика, так и эллипса, более поздним масштабированием аннотации границы, чтобы она полностью покрывала область точками на участке рассеяния, но, к сожалению, эллипс по-прежнему не отображается. Аннотации по-прежнему отображаются как прямоугольник. Считаете ли вы, что настройка внешнего пограничника является виновником? Это произошло со мной после прочтения следующего сообщения http://stackoverflow.com/questions/11588862/changing-the-layer-shape-for-cptplotspaceannotation. – Neckelatius

0

После того, как вы не смогли обработать аннотации, я решил пойти по другому пути. Мое окончательное решение состоит в том, чтобы наложить мой первоначальный график рассеяния на второй, который содержит только один datapoint, а именно центр моего эллипса доверия. Вот код

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

Надеется, что это помогает

Смежные вопросы