2009-07-02 3 views
4

Я пытаюсь исправить старое приложение: у меня есть функция, которая принимает пару углов и рисует 3D-фрагмент разобранной круговой диаграммы. У меня также есть функции, которые берут набор чисел, генерируют углы и вызывают функцию рисования среза несколько раз, пока весь рисунок не будет нарисован.Рисование срезов трехмерной круговой диаграммы в нужном порядке

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

function drawSlice(startAngle, endAngle) 
    // draws a slice as shown in picture 


function drawPie(list of angles to make up pie) 
    for each angle in angles 
    drawSlice(angle) 

// example usage 
drawPie([30,15,40,10,5]) 

Кусочек выглядит следующим образом: alt text http://img233.imageshack.us/img233/2627/slice.png

+0

код? как мы можем знать, что не работает, если мы не знаем, как он должен работать – Eric

+0

не в состоянии опубликовать фактический код, поскольку он не уверен в законности на работе - попробует и объяснит это лучше, и поднимет эквивалентный псевдокод – user4812

ответ

0

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

Некоторый код или другие детали могут помочь вам дать лучший ответ.

2

Возможно, вам придется разделить чертежи на два равных этапа. Оба начинаются с угла, наиболее удаленного от зрителя, и идут в противоположных направлениях.

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

Если есть, например, два ломтика, сначала 80% и начинаются с угла, наиболее удаленного от зрителя, вы разделите его на два ломтика, 50% нарисованных на первом этапе, затем вы нарисуете 20% ломтик, который начинается сверху и идет в другом направлении, и только тогда вы нарисуете оставшиеся 30% первого фрагмента.

Извините за извитое объяснение, я надеюсь, что вы поняли эту идею. ;)

Редактировать: Чтобы проиллюстрировать случай, когда маленький срез перекрывается и перекрывается большим фрагментом. Однако обратите внимание, что это не разобранный пирог, и этот гораздо легче рисовать.

Example chart for a Stack Overflow question

+0

Да, я как бы вижу - Рад, что вы поняли мое бедное начальное объяснение хотя бы! См. Мой ответ, поскольку я думаю, что вы дали мне правильную идею, чтобы начать с ... – user4812

+0

Отлично! Рад помочь! – macbirdie

1

EDIT:

mbeckish прав - это должно исправить. Создайте два списка с помощью метода «мультяшная расы» - т. Е. Продолжайте добавлять в список, пока его общий контент угла не будет превышать другой список, затем измените списки и продолжайте движение. Как только это будет сделано, сначала нарисуйте «меньший». Поскольку это будет содержать не более 180 градусов, он никогда не сможет пересечь опасную точку. Если они равны, это не имеет значения. (Это не красиво)

define clockwiseAngles[], antiClockwiseAngles[] 
define totalClockwiseAngles, totalAntiClockwiseAngles 

for each angle in angles 
    if totalClockwiseAngles > totalAntiClockwiseAngles 
    totalAntiClockwiseAngles += angle 
    AntiClockwiseAngles.push(angle) 
    else 
    totalClockwiseAngles += angle 
    clockwiseAngles.push(angle) 

if totalClockwiseAngles > totalAntiClockwiseAngles 
    // draw all anticlockwise angles 
    // draw all clockwise angles 
else 
    // draw all clockwise angles 
    // draw all anticlockwise angles 
+1

Вы должны убедиться, что срез, который пересекает линию на 180 градусов (то есть срез, который ближе всего к экрану), нарисован последним. В вашем текущем псевдокоде это может быть по часовой стрелке, но срез может быть действительно большим и обернуться вокруг против часовой стрелки. Затем, когда вы нарисуете следующую часть против часовой стрелки, у вас будут проблемы. – mbeckish

0

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

1

Предполагая, что значение угла, когда указует прямо на нас 270, просто вычислить расстояние середины ломтиков от этого шести часов линии:

Math.abs(270 - (startAngle + endAngle)/2) 

Затем сортировать кусочки, основанные на этом расстояние и рисовать в порядке убывания.

+0

+1 Спасибо, это в основном правильный ответ. Он будет работать на любом полузасушливом языке, но в этом конкретном приложении ничего, кроме сортировки high -> low, не реально выполнимо, и мне, вероятно, придется использовать мое более длинное завитое решение. – user4812

+0

См. Мой отредактированный ответ для случая, когда простая формула не работает. – macbirdie

+0

@macbirdie: Вы правы, я поддержал ваш ответ. –