1

I botched together the following code to do a simple rotating radar display.

  1. How can I eliminate the flicker of the line being drawn and then drawn over? Can I use double buffering somehow?

  2. How can I get mouse and keyboard inputs and process/parse them?

My goal is to read angle and distance data from an ultrasonic sensor and display that as a sweep. This data comes from an Arduino with an ultrasonic rangefinder mounted on a servo sweeping backwards and forwards 180 degrees. I also can't quite get the math right. I'd like it to go from 0 to 180, left to right and back depending on the angle data from the Arduino. 0 Deg is 90 Deg off to the right. So I know I have to offset it by 180 Deg but am hopeless at math. The sweep would have to start at 270 Deg and sweep through to 0 Deg. I will have to learn how to read the serial port and parse the data for the display.

Here is my code. I used a tutorial as a base and kind of guessed my way through.

/*
 * simple-drawing.c - demonstrate drawing of pixels, lines, arcs, etc.
 *                    on a window. All drawings are done in black color
 *                    over a white background.
 */

#include <X11/Xlib.h>

#include <stdio.h> #include <stdlib.h> /* getenv(), etc. / #include <unistd.h> / sleep(), etc. */

// Include math library functions. #include <math.h>

/*

  • function: create_simple_window. Creates a window with a white background
  •       in the given size.
    
  • input: display, size of the window (in pixels), and location of the window
  •       (in pixels).
    
  • output: the window's ID.
  • notes: window is created with a black border, 2 pixels wide.
  •       the window is automatically mapped after its creation.
    

/ Window create_simple_window(Display display, int width, int height, int x, int y) { int screen_num = DefaultScreen(display); int win_border_width = 2; Window win;

/* create a simple window, as a direct child of the screen's / / root window. Use the screen's black and white colors as / / the foreground and background colors of the window, / / respectively. Place the new window's top-left corner at / / the given 'x,y' coordinates. */ win = XCreateSimpleWindow(display, RootWindow(display, screen_num), x, y, width, height, win_border_width, BlackPixel(display, screen_num), WhitePixel(display, screen_num));

/* make the window actually appear on the screen. */ XMapWindow(display, win);

/* flush all pending requests to the X server. */ XFlush(display);

return win; }

GC create_gc(Display* display, Window win, int reverse_video) { GC gc; /* handle of newly created GC. / unsigned long valuemask = 0; / which values in 'values' to / / check when creating the GC. / XGCValues values; / initial values for the GC. / unsigned int line_width = 2; / line width for the GC. / int line_style = LineSolid; / style for lines drawing and / int cap_style = CapButt; / style of the line's edje and / int join_style = JoinBevel; / joined lines. */ int screen_num = DefaultScreen(display);

gc = XCreateGC(display, win, valuemask, &values); if (gc < 0) { fprintf(stderr, "XCreateGC: \n"); }

/* allocate foreground and background colors for this GC. */ if (reverse_video) { XSetForeground(display, gc, WhitePixel(display, screen_num)); XSetBackground(display, gc, BlackPixel(display, screen_num)); } else { XSetForeground(display, gc, BlackPixel(display, screen_num)); XSetBackground(display, gc, WhitePixel(display, screen_num)); }

/* define the style of lines that will be drawn using this GC. */ XSetLineAttributes(display, gc, line_width, line_style, cap_style, join_style);

/* define the fill style for the GC. to be 'solid filling'. */ XSetFillStyle(display, gc, FillSolid);

return gc; }

void main(int argc, char* argv[]) { Display* display; /* pointer to X Display structure. / int screen_num; / number of screen to place the window on. / Window win; / pointer to the newly created window. / unsigned int display_width, display_height; / height and width of the X display. / unsigned int width, height; / height and width for the new window. / char display_name = getenv("DISPLAY"); /* address of the X display. / GC gc; / GC (graphics context) used for drawing / / in our window. */

// Added code to select simple black or white color to draw. Colormap screen_colormap; /* color map to use for allocating colors. / XColor black, white; / used for allocation of the given color / / map entries. / Status rc; / return status of various Xlib functions. */

// Johns stuff. This code draws a line from starting co-ordinates at an angle //

int angle=0; int x1,x2,y1,y2; int px,py;

// End

/* open connection with the X server. */ display = XOpenDisplay(display_name); if (display == NULL) { fprintf(stderr, "%s: cannot connect to X server '%s'\n", argv[0], display_name); exit(1); }

/* get the geometry of the default screen for our display. */ screen_num = DefaultScreen(display); display_width = DisplayWidth(display, screen_num); display_height = DisplayHeight(display, screen_num);

/* make the new window occupy 1/9 of the screen's size. */ width = (display_width / 2); height = (display_height / 2); printf("window width - '%d'; height - '%d'\n", width, height);

/* create a simple window, as a direct child of the screen's / / root window. Use the screen's white color as the background / / color of the window. Place the new window's top-left corner / / at the given 'x,y' coordinates. */ win = create_simple_window(display, width, height, 50, 50);

/* allocate a new GC (graphics context) for drawing in the window. */ gc = create_gc(display, win, 0); XSync(display, False);

// Following 3 lines needed or else we just see white background.

/* catch expose events */ XSelectInput(display, win, ExposureMask);

/* wait for the expose event */ XEvent ev; XNextEvent(display, &ev);

// Follwing code borrowed to get colors to draw.
/* get access to the screen's color map. */ screen_colormap = DefaultColormap(display, DefaultScreen(display));

/* allocate the set of colors we will want to use for the drawing. */ rc = XAllocNamedColor(display, screen_colormap, "black", &black, &black); if (rc == 0) { fprintf(stderr, "XAllocNamedColor - failed to allocated 'black' color.\n"); exit(1); } rc = XAllocNamedColor(display, screen_colormap, "white", &white, &white); if (rc == 0) { fprintf(stderr, "XAllocNamedColor - failed to allocated 'white' color.\n"); exit(1); }

/* draw one pixel near each corner of the window */ XDrawPoint(display, win, gc, 5, 5); XDrawPoint(display, win, gc, 5, height-5); XDrawPoint(display, win, gc, width-5, 5); XDrawPoint(display, win, gc, width-5, height-5);

// Do our display. Loop forever because I don't know how to process keystrokes. // If we start from the center of the display, 0 is to the right (E), 90 is to the // bottom (S), 180 (W),270 (N). Don't quite know how to "rotate" the "beam" 180 Deg. // Needs double buffering to remove the flicker. // I would like to make a separate subroutine eg: DrawRadar( int angle, int distance);

x1=width / 2; //Find center of display. y1=height / 2; px=x1; // Previous X and Y py=y1;

while(1){

for(angle=0; angle < 360; angle++) {

// Distance set to 150 pixels. Radar returns value up to 3300 mm. // Will have to scale down. x2=x1 + cos((angle * M_PI) / 180) * 150; // Must convert to radians. y2=y1 + sin((angle * M_PI) / 180) * 150; // " " " "

XSetForeground(display, gc, black.pixel);  // 
XDrawLine(display, win, gc, x1, y1, x2, y2);
px=x2;
py=y2;
XFlush(display);      // Display what we've drawn.
usleep(3500);         // Wait so eye can see it.
XSetForeground(display, gc, white.pixel);  // Rub out the line we just drew.
XDrawLine(display, win, gc, x1, y1, px ,py);
XFlush(display);      // Causes flickering but only way at the moment.
XSetForeground(display, gc, black.pixel);
usleep(3500);

} } // End. Never get past here.

/* flush all pending requests to the X server. */ XFlush(display); XSync(display, False);

/* make a delay for a short period. */ sleep(4);

/* close the connection to the X server. */ XCloseDisplay(display); }

I'm simply trying to draw a moving line without flicker. I understand the concept but am a crap coder. Any help would be appreciated.

tripleee
  • 117
  • 4
John Telek
  • 11
  • 1
  • The Unix & Linux stack exchange forum may be a better spot to post this. Most folks here are working with OpenGL, DirectX, Vulkan, etc. – pmw1234 Nov 01 '22 at 15:07

0 Answers0