Angelore
Angelore

Reputation: 63

Drawing a line with perpendicular decoration

I need to draw a line in the following manner:

Example  

For now, it will be only drawn in code, no user input.

My question is, how to draw perpendiculars to a line, if I draw it point by point? (Obviously, this will be the case, because drawing with bezier curves will not give me the possibility to somehow impact the drawing).

The closest answer I found was possibly this one, but I can't reverse the equations to derive C. Also there is no length of the decoration mentioned, so I think this will not work as I'd like it to.

Upvotes: 2

Views: 831

Answers (2)

GameAlchemist
GameAlchemist

Reputation: 19294

Find the segment perpendicular to another one is quite easy.
Say we have points A, B.
Compute vector AB.
Normalize it to compute NAB (== the 'same' vector, but having a length of 1).
Then if a vector has (x,y) as coordinates, its normal vector has (-y,x) as coordinates, so you can have PNAB easily (PNAB = perpendicular normal vector to AB).

// vector AB
var ABx =  B.x - A.x ;
var ABy =  B.y - A.y ;
var ABLength = Math.sqrt( ABx*ABx + ABy*ABy );
// normalized vector AB
var NABx = ABx / ABLength;
var NABy = ABy / ABLength;
// Perpendicular + normalized vector.
var PNABx = -NABy ;
var PNABy =  NABx ;

last step is to compute D, the point that is at a distance l of A : just add l * PNAB to A :

// compute D = A + l * PNAB
var Dx = A.x + l* PNAB.x;
var Dy = A.y + l *PNAB.y;

Updated JSBIN :

http://jsbin.com/bojozibuvu/1/edit?js,output

Edit : A second step is to draw the decorations at regular distance, since it's Christmas time, here's how i would do it :

http://jsbin.com/gavebucadu/1/edit?js,console,output

function drawDecoratedSegment(A, B, l, runningLength) {
    // vector AB
    var ABx = B.x - A.x;
    var ABy = B.y - A.y;
    var ABLength = Math.sqrt(ABx * ABx + ABy * ABy);
    // normalized vector AB
    var NABx = ABx / ABLength;
    var NABy = ABy / ABLength;
    // Perpendicular + normalized vector.
    var PNAB = {  x: -NABy,  y: NABx    };
    // 
    var C = { x: 0, y: 0    };
    var D = { x: 0, y: 0    };
    //
    drawSegment(A, B);
    // end length of drawn segment
    var endLength = runningLength + ABLength;
    // while we can draw a decoration on this line
    while (lastDecorationPos + decorationSpacing < endLength) {
        // compute relative position of decoration.
        var decRelPos = (lastDecorationPos + decorationSpacing) - runningLength;
        // compute C, the start point of decoration
        C.x = A.x + decRelPos * NABx;
        C.y = A.y + decRelPos * NABy;
        // compute D, the end point of decoration      
        D.x = C.x + l * PNAB.x;
        D.y = C.y + l * PNAB.y;
        // draw
        drawSegment(C, D);
        // iterate
        lastDecorationPos += decorationSpacing;
    }
    return ABLength;
}

Upvotes: 5

MBo
MBo

Reputation: 80177

All you need is direction of curve (or polyline segment) in every point, where you want to draw perpendicular. If direction vector in point P0 is (dx, dy), then perpendicular (left one) will have direction vector (-dy, dx). To draw perpendicular with length Len, use this pseudocode:

Norm = Sqrt(dx*dx + dy*dy)   //use Math.Hypot if available
P1.X = P0.X - Len * dy / Norm
P1.Y = P0.Y + Len * dx / Norm

P.S. If you know direction angle A, then direction vector

(dx, dy) = (Cos(A), Sin(A))

and you don't need to calculate Norm, it is equal to 1.0

Upvotes: 1

Related Questions