Digital Diferential Analizer Dotted Line

1.1k views Asked by At

Im using de DDA (Digital Diferential Analizer) to make a line, and thought I know maybe using de DrawLine the way I am, just run along with it. Im trying to make different types of lines like dashed or dotted, etc. Im thinking in makeing the for from below jump some numbers to make a dotted line. But I cant still find a way todo it. This is what I have so far:

public void paint(Graphics g) {
        super.paint(g);
        int dot=0;
        int x1 = pointStart.x;
        int x2 = pointEnd.x;
        int y1 = pointStart.y;
        int y2 = pointEnd.y;
        float dx, dy, m, y, x;
        if (x1>x2){
            int ax = x2;
            int ay = y2;
            x2 = x1;
            x1 = ax;
            y2 = y1;
            y1 = ay;
        }
        dx = x2 - x1;
        dy = y2 - y1;
        m = dy/dx;
        if (m>=-1&&m<=1){
            dot = (int)dx/4;
            y = y1;
            System.out.println(m);
            for (x = x1 ; x <= x2;x++){
                //if (x>=dot&&x<=dot+10||x>=dot*2&&x<=dot*2+10||x>=dot*3&&x<=dot*3+10){
                    g.drawLine((int)x, (int)Math.round(y), (int)x, (int)Math.round(y));
                    y+=m;
                //}
            }   
        }
        else{
            x = x1;
            System.out.println(m);
            for (y = y1 ; y <= y2;y++){
                g.drawLine((int)Math.round(x), (int)y, (int)Math.round(x), (int)y);
                x+=1/m; 
            }
        }

        /*if (pointStart != null) {
            if (x1>)        
            g.setColor(Color.RED);
            //g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
            g.drawLine(x1, y1, x1, y1);
        }*/

    }

Any ideas?

1

There are 1 answers

0
Spektre On
  1. you need draw line function (in your case g.drawline(x0,y0,x1,y1); ).
  2. dont care about color (you can play with it later)
  3. you need definition of your pattern (size of lines and spaces in pixels)
  4. for example int pattern[]={10,-5,0} (10px line, then 5px space, 0 means repeat from beginning) ... -values are spaces + values are lines
  5. you need 'global' state (actual index in pattern and actual pixel length drawed) also you can have global pattern pointer or encapsulate all in class/struct.

ok so the basic idea is to segmentate any line to selected pattern for example like this:

//---------------------------------------------------------------------------
// pattern draw state
int    _pattern_ix=0; // actual index in pattern need to reset it to zero before any pattern change
double _pattern_l=0;  // already drawed or skipped pixels from actual pattern[_pattern_ix]
// predefined patterns
int    _pattern_dash_dash[]={ 10,-10,        0 };
int    _pattern_dash_dot[] ={ 10,- 5,  1,- 5,0 };
int    _pattern_dot_dot[]  ={  1,- 5,        0 };
//---------------------------------------------------------------------------
// draw line function
void drawline(int x0,int y0,int x1,int y1)
    {
    // this is just borland GDI access to draw line function
    Form1->Canvas->MoveTo(x0,y0);
    Form1->Canvas->LineTo(x1,y1);
    }
//---------------------------------------------------------------------------
void pattern_line(int x0,int y0,int x1,int y1,int *pattern)
    {
    int p;
    double x,y,xx,yy,dx,dy,dl,t,dt;
    dx=x1-x0;
    dy=y1-y0;
    dl=sqrt((dx*dx)+(dy*dy));
    dx/=dl; dy/=dl;
    for (t=0.0,dt=0.0;dl>=0.5;)
        {
        p=pattern[_pattern_ix];
        if (p<0) // skip
            {
            dt=-p-_pattern_l;                      // t=space to skip [px]
            if (dt>dl) { _pattern_l+=dl; return; } // space is bigger then rest of line
            dl-=dt; t+=dt; _pattern_l=0.0;         // update line params and continue to next pattern entry
            }
        else     // draw
            {
            dt=+p-_pattern_l;                     // t=space to draw [px]
            x=x0+double(t*dx);                    // actual point pos
            y=y0+double(t*dy);                    // space is bigger then rest of line
            if (dt>dl) { _pattern_l+=dl; drawline(x,y,x1,y1); return; }
            dl-=dt; t+=dt; _pattern_l=0.0;        // update line params
            xx=x0+double(t*dx);                   // actual point pos
            yy=y0+double(t*dy);
            drawline(x,y,xx,yy);                  // draw line and continue to next pattern entry
            }
        _pattern_ix++;
        if (!pattern[_pattern_ix]) _pattern_ix=0;
        }
    }
//---------------------------------------------------------------------------
void main()
    {
    // borland GDI clear screen and color settings
    Canvas->Brush->Color=clBlack;
    Canvas->Pen->Color=clWhite;
    Canvas->FillRect(ClientRect);
    // draw dash-dot-ed rectangle
    int x0,x1,y0,y1;
    x0=30; x1=200;
    y0=30; y1=100;
    pattern_line(x0,y0,x1,y0,_pattern_dash_dot);
    pattern_line(x1,y0,x1,y1,_pattern_dash_dot);
    pattern_line(x1,y1,x0,y1,_pattern_dash_dot);
    pattern_line(x0,y1,x0,y0,_pattern_dash_dot);
    }
//---------------------------------------------------------------------------

and do not forget to reset pattern ix,l to zero before any pattern style change. Code is not optimized so its pretty slow but simple enough to understand i hope.