2013-04-07 3 views
8

Я ищу способ сделать линию кривой через несколько точек. Было бы предпочтительнее использовать 3 балла, хотя я считаю, что для того, чтобы дать контекст углу линии, входящей в точку, может потребоваться больше, чтобы дать контекст кривой, так сказать.Как сделать линию кривой через точки

В общем, начальная точка P1, контрольная точка P2 и конечная точка P3, линия должна быть кривой P2 от P1, а затем кривой от P2 до P3.

На самом деле здесь является прекрасным примером эффекта я хотел бы достичь:

Irwin Hall Spline

Если бы я мог сделать это, я действительно был бы вечно благодарен!

В Java до сих пор, я пытался играть с вещами, такими, как QuadCurve2D.Double, Cub icCurve2D.Double, а также Path2D.Double (с использованием curveTo с Path2D.Double), но безрезультатно - кривые, которые окрашены не даже близко к проходящей через указанная контрольная точка.

Вот изображение из методов я пытался до сих пор:

enter image description here

А вот код, который я использовал для создания точек и кривых на изображении:

Graphics2D g = (Graphics2D) window.getGraphics(); 
    g.setColor(Color.blue); 
    int d = 4; 

    // P0 
    int x0 = window.getWidth()/8; 
    int y0 = 250; 
    g.drawString("P0", x0, y0 + 4*d); 
    g.fillRect(x0, y0, d, d); 

    // P1 
    int x1 = (window.getWidth()/7)*2; 
    int y1 = 235; 
    g.drawString("P1", x1, y1 + 4*d); 
    g.fillRect(x1, y1, d, d); 

    // P2 
    int x2 = (window.getWidth()/2); 
    int y2 = 200; 
    g.drawString("P2", x2, y2 - 2*d); 
    g.fillRect(x2, y2, d, d); 

    // P3 
    int x3 = (window.getWidth()/7)*5; 
    int y3 = 235; 
    g.drawString("P3", x3, y3 + 4*d); 
    g.fillRect(x3, y3, d, d); 

      // P4 
    int x4 = (window.getWidth()/8)*7; 
    int y4 = 250; 
    g.drawString("P4", x4, y4 + 4*d); 
    g.fillRect(x4, y4, d, d); 

    g.setColor(Color.cyan); 
    QuadCurve2D quadCurve = new QuadCurve2D.Double(x0, y0, x2, y2, x4, y4); 
    g.draw(quadCurve); 


    g.setColor(Color.YELLOW); 
    CubicCurve2D.Double cubicCurve = new CubicCurve2D.Double((double)x0, (double)y0, 
                  (double)x1, (double)y1, 
                  (double)x2, (double)y2, 
                  (double)x4, (double)y4); 
    g.draw(cubicCurve); 


    g.setColor(Color.red);  
    Path2D.Double path1 = new Path2D.Double(); 
    path1.moveTo(x1, y1); 
    path1.curveTo(x0, y0, x2, y2, x4, y4); 
    g.draw(path1); 

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

Я был бы очень благодарен за любую помощь, предлагаемую - Спасибо заранее.

+0

Позвольте пояснить, вы просите, чтобы можно было нарисовать кривую через массив точек? –

+0

Да, считайте, что каждая точка сплайна Irwin-Hall является элементом массива. –

ответ

9

Я думаю, вам не хватает идеи того, что контрольная точка есть. Контрольные точки, как правило, не находятся на самом пути. Вместо этого они контролируют, как образуется кривая пути между точками. Подробности см. На странице spline tutorial.

Теперь к проблеме у вас есть точки на кривой, но нет фактических контрольных точек. Существуют некоторые методы, такие как Cardinal Spline, для получения контрольных точек, а затем переход к одному из API-интерфейсов рисования кривой, которые вы упомянули. Вероятно, вам нужна опция Path2D.Double, чтобы вы могли плавно объединять отдельные кривые.

Таким образом, для рисования от Р1 до Р2 Р3, а

Path2D.Double path1 = new Path2D.Double(); 
path1.moveTo(x1, y1); 
path1.curveTo(x0, y0, x2, y2, x4, y4); 
g.draw(path1); 

Вы хотите

Path2D.Double path1 = new Path2D.Double(); 
path1.moveTo(x1, y1); 
path1.curveTo(cx1a, cy1a, cx1b, cy1b, x2, y2); 
path1.curveTo(cx2a, cy2a, cx2b, cy2b, x3, y3); 
g.draw(path1); 

где cx и cy координаты производных контрольные точки, две контрольных точек на кубический сплайн сегмент. Возможно,

cx1a = x1 + (x2 - x1)/3; 
cy1a = y1 + (y2 - y1)/3; 
cx1b = x2 - (x3 - x1)/3; 
cy1b = y2 - (y3 - y1)/3; 
cx2a = x2 + (x3 - x1)/3; 
cy2a = y2 + (y3 - y1)/3; 
cx2b = x3 - (x3 - x2)/3; 
cy2b = y3 - (y3 - y2)/3; 

картина здесь является то, что для внутренних точек (только P2 в этом случае) в контрольных точках до и после него (C1b и c2a) смещены по наклону линии между точками до и после него (P1 и P3). Для краевых точек контрольные точки основаны на наклоне между этой точкой и ближайшей ближайшей точкой.

Если у вас есть информация о домене, вы можете выбрать различные контрольные точки. Например, вы можете заставить склоны в конечных точках равняться 0.

+0

Довольно уверены, что cx1b и cy1b не должны дублироваться? Должны ли они не быть cx1a cy1a cx1b cy1b? –

+0

Спасибо @ JamesC. Исправлено. – xan

+0

Если это не так много проблем, вы могли бы пролить свет на то, почему вы выбираете такие значения x и y для построения контрольных точек? Почему все, кроме последней пары контрольных точек, используют x1, y1? Также во второй паре cx1b и cy1b они, похоже, зависят от положения точки после точки, к которой приближается кривая, но в последней паре вы, очевидно, не можете сделать этот дополнительный шаг, так как вы приближаетесь к этой последней точке. Поэтому я предполагаю, что вы, возможно, используете точку будущего x3, y3, чтобы оправдать угол кривой, приближающийся ко второй точке, видя, что тогда она будет плавно переходить к будущей точке? –

2

хорошо, возможно, это может помочь: P

Катмулл Rom кривые на примере тех же принципов, отличный Ланг ... http://schepers.cc/svg/path/dotty.svg

+0

сплайны Catmull-rom отличаются от сплайнов Irwin-hall способом, которым рисуется кривая. Проверьте этот ресурс и нарисуйте некоторые моменты, http://blog.ivank.net/interpolation-with-cubic-splines.html –

+0

Спасибо за ссылку Джобан, если вы считаете [этот пример] (http://postimg.org/ image/izjajqfw7 /), который я создал по ссылке, которую вы предоставили, вы можете увидеть кривую (по крайней мере, в моем случае), неправомерно создаст впечатление, что между последним и точками существует гораздо большее значение. Пример Catmull-Rom, который плавает, связан с приемлемым, однако реализация не ясна - любые идеи плавают? –

+0

Итак, тогда вы хотите сплайн-шлем, потому что, возможно, это будет немного легче. –

2

В основном то, что вы спрашиваете, как для кубического сплайна Интерполяция, я был в состоянии найти эту программу онлайн Interp2.java. Он фактически включает полиномиальный сплайн и кубический сплайн.

К сожалению, его апплет, а не фактический класс, но вы все равно можете просмотреть код, узнаете, как они это сделали. Это всегда хорошо.

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