2011-01-12 3 views
24

Ich brauche einen schnellen Algorithmus für die Berechnung von Koordinaten für eine Linie zwischen zwei Punkten. Ich habe versucht, eine gute JavaScript-Implementierung von Bresenham zu finden, aber es gibt zu viele und ziemlich verwirrende Veröffentlichungen. In wikipedia - here die schnellste und einfachste Form (ohne Spaltungen und Fehlerberechnung für beide Richtungen) in Pseudo-Code wie folgt dargestellt:Bresenham Algorithmus in Javascript

function line(x0, y0, x1, y1) 
    dx := abs(x1-x0) 
    dy := abs(y1-y0) 
    if x0 < x1 then sx := 1 else sx := -1 
    if y0 < y1 then sy := 1 else sy := -1 
    err := dx-dy 

    loop 
    setPixel(x0,y0) 
    if x0 = x1 and y0 = y1 exit loop 
    e2 := 2*err 
    if e2 > -dy then 
     err := err - dy 
     x0 := x0 + sx 
    if e2 < dx then 
     err := err + dx 
     y0 := y0 + sy 
    end loop 

Kennen Sie eine einfache und robuste Implementierung JavaScript Bresenham basierend auf dieser Pseudo-Code?

EDIT

Vielen Dank allen! Dies ist, was ich mit am Ende kam:

function calcStraightLine (startCoordinates, endCoordinates) { 
    var coordinatesArray = new Array(); 
    // Translate coordinates 
    var x1 = startCoordinates.left; 
    var y1 = startCoordinates.top; 
    var x2 = endCoordinates.left; 
    var y2 = endCoordinates.top; 
    // Define differences and error check 
    var dx = Math.abs(x2 - x1); 
    var dy = Math.abs(y2 - y1); 
    var sx = (x1 < x2) ? 1 : -1; 
    var sy = (y1 < y2) ? 1 : -1; 
    var err = dx - dy; 
    // Set first coordinates 
    coordinatesArray.push(new Coordinates(y1, x1)); 
    // Main loop 
    while (!((x1 == x2) && (y1 == y2))) { 
     var e2 = err << 1; 
     if (e2 > -dy) { 
     err -= dy; 
     x1 += sx; 
     } 
     if (e2 < dx) { 
     err += dx; 
     y1 += sy; 
     } 
     // Set coordinates 
     coordinatesArray.push(new Coordinates(y1, x1)); 
    } 
    // Return the result 
    return coordinatesArray; 
    } 

Antwort

42

Ihren gelieferten Pseudo-Code in JavaScript Umschreiben:

function line(x0, y0, x1, y1){ 
    var dx = Math.abs(x1-x0); 
    var dy = Math.abs(y1-y0); 
    var sx = (x0 < x1) ? 1 : -1; 
    var sy = (y0 < y1) ? 1 : -1; 
    var err = dx-dy; 

    while(true){ 
    setPixel(x0,y0); // Do what you need to for this 

    if ((x0==x1) && (y0==y1)) break; 
    var e2 = 2*err; 
    if (e2 >-dy){ err -= dy; x0 += sx; } 
    if (e2 < dx){ err += dx; y0 += sy; } 
    } 
} 

Beachten Sie, dass Schwimmer kann direkt Vergleich fehlschlagen, wie Sie Schritt (obwohl es nicht sollte, wenn durch ganzzahlige Beträge treten, könnte es, wenn entweder Endpunkt ist nicht ganzzahligen), so, anstatt direkt die Endpunkte zu vergleichen Sie könnten ein epsilon verwenden möchten:

if (Math.abs(x0-x1)<0.0001 && Math.abs(y0-y1)<0.0001) break; 

Dies wird zwangsläufig verlangsamen Sie aber tue dies nur, wenn du mit nicht-ganzen Zahlen arbeitest.

+2

Brasenham soll sowieso nur auf ganzen Zahlen arbeiten. Es wird verwendet, um zu berechnen, welche Pixel zu malen sind, um eine Linie zu zeichnen. –

+1

Ich mag diese, aber ich denke, dass es weiter verbessert werden kann, indem die Pause zugunsten der realen Schleifenbedingung entfernt wird und die Multiplikation mit der Verschiebung um zwei gemacht wird. –

+2

Die Bit-Verschiebung ist vielleicht ein Haar schneller, aber ich bezweifle, dass das Ändern der Schleife die Leistung beeinträchtigen würde. Sie könnten es leicht in 'while (x0! = X1 || y0! = Y1)' ändern und das 'if/break' entfernen, aber Sie müssten einen weiteren Aufruf von' setPixel' vor/nach der Schleife ausführen der Endpunkt der Linie korrekt und der Randfall. – Phrogz

Verwandte Themen