2016-04-23 2 views
4

Я пытаюсь рисовать элементы индикатора скорости с использованием Core Graphics на OSX. Я почти получил его, но мне нужна небольшая помощь в центре, который находится внутри калибра. Вот образ того, что я пытаюсь сделать:Рисование спидометра с базовой графикой на OSX в NSView

enter image description here

Вот образ того, что у меня до сих пор:

enter image description here

Я знаю, как рисовать круг кольца и как рисовать сегменты на основе вокруг центра датчика, например так:

- (void)drawOuterGaugeRingsInRect:(CGContextRef)contextRef rect:(NSRect)rect { 


    CGContextSetLineWidth(contextRef,self.gaugeRingWidth); 

    CGContextSetStrokeColorWithColor(contextRef, [MyColors SpeedGaugeOuterRingGray].CGColor); 
    CGFloat startRadians = 0; 
    CGFloat endRadians = M_PI*2; 
    CGFloat radius = self.bounds.size.width/2 - 5; 

    CGContextAddArc(contextRef, CGRectGetMidX(rect),CGRectGetMidY(rect),radius,startRadians,endRadians,YES); 
    //Render the outer gauge 
    CGContextStrokePath(contextRef); 

    //Draw the inner gauge ring. 
    radius -= self.gaugeRingWidth; 
    CGContextSetStrokeColorWithColor(contextRef, [MyColors SpeedGaugeInnerRingGray].CGColor); 
    CGContextAddArc(contextRef, CGRectGetMidX(rect),CGRectGetMidY(rect),radius,startRadians,endRadians,YES); 

    //Render the inner gauge 
    CGContextStrokePath(contextRef); 

    radius -= self.gaugeRingWidth; 

    //Draw and fill the gauge background 

    CGContextSetFillColorWithColor(contextRef, [MyColors SpeedGaugeCenterFillBlack ].CGColor); 
    CGContextSetStrokeColorWithColor(contextRef, [MyColors SpeedGaugeCenterFillBlack].CGColor); 
    CGContextAddArc(contextRef, CGRectGetMidX(rect),CGRectGetMidY(rect),radius,startRadians,endRadians,YES); 

    //Render and fill the gauge background 
    CGContextDrawPath(contextRef, kCGPathFillStroke); 


    /*BLUE CIRCULAR DIAL */ 
    //Prepare to draw the blue circular dial. 
    radius -= self.gaugeRingWidth/2; 

    //Adjust gauge ring width 
    CGContextSetLineWidth(contextRef,self.gaugeRingWidth/2); 

    CGContextSetStrokeColorWithColor(contextRef, [MyColors SpeedGaugeBlue].CGColor); 

    CGFloat startingRadians = [MyMathHelper degressToRadians:135]; 
    CGFloat endingRadians = [MyMathHelper degressToRadians:45]; 


    CGContextAddArc(contextRef, CGRectGetMidX(rect),CGRectGetMidY(rect),radius,startingRadians,endingRadians,NO); 

    //Render the blue gauge line 
    CGContextStrokePath(contextRef); 
} 

код выше, называется в drawRect: метод в моем NSView

Ключевой раздел является код здесь:

- (void)drawInnerDividerLines:(CGContextRef)context rect:(NSRect)rect { 

    CGFloat centerX = CGRectGetMidX(rect); 
    CGFloat centerY = CGRectGetMidY(rect); 


    CGContextSetLineWidth  (context, 3.0); 
    CGContextSetRGBStrokeColor (context, 37.0/255.0, 204.0/255.0, 227.0/255.0, 0.5); 



    CGFloat destinationX = centerX + (centerY * (cos((135)*(M_PI/180)))); 
    CGFloat destinationY = centerY + (centerX * (sin((135)*(M_PI/180)))); 

    NSPoint destinationPoint = NSMakePoint(destinationX, destinationY); 


    CGContextMoveToPoint(context, centerX, centerY); 

    CGContextAddLineToPoint(context, destinationPoint.x, destinationPoint.y); 

    CGContextStrokePath(context); 

} 

Я понимаю, что здесь происходит, но проблема, которую я пытаюсь решить рисует маленькие линии, прочь внутренний синюю линию, которая простирается к центральной точке Вид, но не тянет до центра. Я немного не уверен в том, как изменить математику и логику рисования, чтобы достичь этого. Вот единица окружности I, основанная на углах для Core Graphics Drawing.

enter image description here

Основные проблемы, я пытаюсь решить, являются:

  1. Как определить правильную начальную точку прочь светло-голубой внутренней линии в качестве точки гляделки для каждого датчика клеща. Прямо сейчас, я рисую полную линию от центра до края калибра.

  2. Как контролировать длину указателя галочки по мере того, как он рисует направленный к центру от его точки происхождения на синей линии.

Любые советы или советы, которые указывали бы на меня в правильном направлении для решения этого вопроса, будут оценены по достоинству.

ответ

2

Я рекомендую использовать векторы. Вы можете найти строку в любую точку на окружности заданного угол вычисляя:

dirX = cos(angle); 
dirY = sin(angle); 
startPt.x = center.x + innerRadius * dirX; 
startPt.y = center.y + innerRadius * dirY; 
endPt.x = center.x + outerRadius * dirX; 
endPt.y = center.y + outerRadius * dirY; 

Вы можете построить линию между startPt и endPt.

+0

Было именно то, что мне было нужно, спасибо за это! – zic10

1

Любые советы или советы, которые указывают на меня в правильном направлении для решения этого вопроса, будут оценены.

Учитывая точку на окружности вашего круга на определенный угол вокруг центра вы можете сформировать правильный прямоугольный треугольник, радиус гипотенузы, а две другие стороны параллельны осям у х & (на какое-то время игнорируйте вырожденный случай, когда точка находится на 0, 90, 180 или 270 градусов). Учитывая, что с грехом & cos formula (помните SOHCAHTOA из школы) и некоторой базовой математикой вы можете вычислить координаты точки и используя это, нарисуйте радиус от центра до точки.

Конечные точки метки «тика» просто лежат на кругах разных радиусов, поэтому одна и та же математика даст вам конечные точки, и вы можете нарисовать галочку. Вам просто нужно определить радиусы этих кругов, то есть расстояние вдоль вашего первоначального радиуса должно быть конечными точками галочки.

HTH

0

Другой подход, чтобы избежать тригонометрии, состоит в том, чтобы повернуть матрицу преобразования и просто нарисовать вертикальную или горизонтальную линию.

// A vertical "line" of width "width" along the y axis at x==0. 
NSRect tick = NSMakeRect(-width/2.0, innerRadius, width, outerRadius - innerRadius); 
NSAffineTransform* xform = [NSAffineTransform transform]; 
// Move the x and y axes to the center of your speedometer so rotation happens around it 
[xform translateXBy:center.x yBy:center.y]; 
// Rotate the coordinate system so that straight up is actually at your speedometer's 0 
[xform rotateByDegrees:135]; 
[xform concat]; 
// Create a new transform to rotate back around for each tick. 
xform = [NSAffineTransform transform]; 
[xform rotateByDegrees:-270.0/numTicks]; 
for (int i = 0; i < numTicks; i++) 
{ 
    NSRectFill(tick); 
    [xform concat]; 
} 

Вы, вероятно, хотите, чтобы обернуть это в [NSGraphicsContext saveGraphicsState] и [NSGraphicsContext restoreGraphicsState] поэтому матрица преобразования восстанавливается, когда вы закончите.

Если вы хотите два разных типа меток (основных и второстепенных), то есть два разных прямоугольника и выберите один на основе i % 10 == 0 или что-то еще. Возможно, также переключить цвет. И т. Д.

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

  • Нет связанных вопросов^_^