Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Line-drawing algorithm prints nonsensical intermediate Y values. Where is the problem?

+2
−0

This question was originally asked in SE.


I have a program that draws lines using line drawing algorithms. I use gcc 5.2.1 on Xubuntu 15.10 to compile it.

Executing it throws a "Segment violation" fault. Further investigation let me isolate the problem in this MCVE:

#include <stdio.h>
#include <stdlib.h>

typedef unsigned int uint;
typedef unsigned char byte;

typedef struct {
    uint x;
    uint y;
} point;

typedef struct {
    point start;
    point end;
} line;

line new_line(point start, point end) {
    line l;
    l.start = start; l.end = end;
    return l;
}

point new_point(uint x, uint y) {
    point p;
    p.x = x; p.y = y;
    return p;
}

byte points_equal(point p1, point p2) {
    int equal = (p1.x == p2.x && p1.y == p2.y) ? 1 : 0;
    return equal;
}

double line_slope(line l) {
    return (double) (l.end.y - l.start.y) / (l.end.x - l.start.x);
}

/* Naive line drawing algorithm: assumes line in 1st octant */
point * naive(line l) {
    uint numelems = abs( l.end.x - l.start.x );
    double m = line_slope(l);
    point * tbl = calloc(numelems + 1, sizeof *tbl);
    if (tbl == NULL) return NULL;
    int x, nt;
    double b = (double) l.start.y - ((double) l.start.x * m);
    tbl[0] = l.start;
    tbl[numelems] = l.end;
    for (x = l.start.x + 1, nt = 1; nt < numelems; x++, nt++) {
        tbl[nt].x = x;
        tbl[nt].y = (int) ( m*x + b );
    }
    return tbl;
}

/* Main program */
int main() {
    line l = new_line( new_point( -345, -236 ), new_point( -25, -3 ) );
    point *tbl = naive( l );
    if (tbl != NULL) {
        uint n = 0;
        do {
            printf("(%d,%d)\n", tbl[n].x, tbl[n].y);
        } while ( !points_equal( tbl[n++], l.end ) );
        free(tbl);
    }
    return 0;
}

The output of this program is

(-345,-236)
(-344,1167693998)
(-343,1167693999)
(-342,1167693999)
(-341,1167694000)
(-340,1167694001)

/* output continues */

(-30,1167694226)
(-29,1167694227)
(-28,1167694228)
(-27,1167694229)
(-26,1167694229)
(-25,-3)

As you can see, the Y coordinates are all wrong (huge positive numbers), instead of smoothly going up from -236 to -3, as it should when drawing lines.

Here comes my question: What does this mean? Would the structure be interfering with the cast? Can something like that actually happen? Is there any other problem I'm not seeing here?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+2
−0

I answered myself as it can be found here.


Silly me! The root of the entire problem was the type used in both point.x and point.y:

typedef unsigned int uint;

typedef struct {
    uint x;
    uint y;
} point;

As both are unsigned integers, they "wrap up" once they receive a negative value, just like in the MCVE. This gets corrected by just changing uint to int:

typedef struct {
    int x;
    int y;
} point;

So keep this in mind when using signed and unsigned numbers!

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »