Esempio n. 1
0
skO *parse_string_literal (char **next, jmp_buf jmp)
{
	skO *list;

	if (**next != '"')
		return NULL;

	++*next;
	list = skO_list_new();

	while (**next != '"')
		sk_list_append(list, parse_character(next, jmp));
	++*next;

	#ifdef SK_PARSER_DEBUG
	printf("Parsed STRING\n");
	#endif
	return list;
}
Esempio n. 2
0
bool transform_cg_polygon
(
    sk_cg_geometry *source,
    cg_element **transformation,
    sk_cg_geometry *dest
)
{
    if (!source || !transformation || !dest)
    {
        return false;
    }

    sk_iterator it;

    if (dest != source)
    {
        sk_list_init(&dest->geometry.polygon.points, NULL);
        sk_list_begin(&it, &source->geometry.polygon.points);
        while(it.has_next(&it))
        {
            sk_cg_point *clone = ALLOC(*clone, 1);
            sk_cg_point *element = it.next(&it);
            clone->x = element->x;
            clone->y = element->y;
            sk_list_append(&dest->geometry.polygon.points, clone);
        }
        it.destroy(&it);
    }

    sk_list_begin(&it, &dest->geometry.polygon.points);
    sk_cg_point *point = NULL;
    while (it.has_next(&it))
    {
        point = it.next(&it);
        transform_cg_point(point, transformation, point);
    }
    it.destroy(&it);

    // FIXME
    // Check return values
    return true;
}
Esempio n. 3
0
bool clip_cg_polygon
(
    sk_cg_geometry *source,
    int x_min,
    int y_min,
    int x_max,
    int y_max,
    sk_list *dest
)
{
    if (!source || !dest)
    {
        return false;
    }

    sk_cg_point V0 =
    {
        .x = x_min,
        .y = y_min
    };
    sk_cg_point V1 =
    {
        .x = x_max,
        .y = y_min
    };
    sk_cg_point V2 =
    {
        .x = x_max,
        .y = y_max
    };
    sk_cg_point V3 =
    {
        .x = x_min,
        .y = y_max
    };

    struct w_a_node;
    typedef struct w_a_node w_a_node;
    struct w_a_node
    {
        sk_cg_point *point;
        w_a_node    *A_prev;
        w_a_node    *A_next;
        w_a_node    *B_prev;
        w_a_node    *B_next;
        bool         in;
    };

    bool retval = true;

    // Initialize the output list
    if (!sk_list_init(dest, NULL))
    {
        retval = false;
        goto dest_init_fail;
    }

    // Initialize the clipping polygon
    sk_cg_geometry clipping_polygon;
    clipping_polygon.type = POLYGON;
    if (!(  sk_list_init(&clipping_polygon.geometry.polygon.points, NULL)
         && sk_list_append(&clipping_polygon.geometry.polygon.points, &V0)
         && sk_list_append(&clipping_polygon.geometry.polygon.points, &V1)
         && sk_list_append(&clipping_polygon.geometry.polygon.points, &V2)
         && sk_list_append(&clipping_polygon.geometry.polygon.points, &V3)
         )
       )
    {
        retval = false;
        goto clipping_poly_init_fail;
    }

    w_a_node *A_head;
    w_a_node *B_head;
    w_a_node **curr;
    w_a_node *prev;

    // Establish the Weiler-Atherton list for the clipping polygon
    curr = &A_head;
    prev = NULL;
    sk_iterator A_it;
    if (!sk_list_begin(&A_it, &clipping_polygon.geometry.polygon.points))
    {
        retval = false;
        goto A_W_A_list_fail;
    }
    while (A_it.has_next(&A_it))
    {
        *curr = ALLOC(*(*curr), 1);
        (*curr)->point = A_it.next(&A_it);
        (*curr)->in = is_inside((*curr)->point, source);
        (*curr)->A_prev = prev;
        prev = *curr;

        curr = &(*curr)->A_next;
    }
    *curr = A_head;
    A_head->A_prev = prev;
    A_it.destroy(&A_it);

    // Establish the Weiler-Atherton list for the source polygon
    curr = &B_head;
    prev = NULL;
    sk_iterator B_it;
    bool found_out = false;
    bool found_in = false;
    if (!sk_list_begin(&B_it, &source->geometry.polygon.points))
    {
        retval = false;
        goto B_W_A_list_fail;
    }
    while (B_it.has_next(&B_it))
    {
        *curr = ALLOC(*(*curr), 1);
        (*curr)->point = B_it.next(&B_it);
        (*curr)->in = is_inside((*curr)->point, &clipping_polygon);
        if (!(*curr)->in)
        {
            found_out = true;
        }
        if ((*curr)->in)
        {
            found_in = true;
        }
        (*curr)->B_prev = prev;
        prev = *curr;

        curr = &(*curr)->B_next;
    }
    *curr = B_head;
    B_head->B_prev = prev;
    B_it.destroy(&B_it);

    // If source is entirely inside the clipping polygon, it is already clipped.
    if (!found_out)
    {
        sk_cg_geometry *poly = ALLOC(*poly, 1);
        poly->type = POLYGON;

        sk_iterator it;
        sk_list_begin(&it, &source->geometry.polygon.points);
        while (it.has_next(&it))
        {
            sk_list_append(&poly->geometry.polygon.points, it.next(&it));
            sk_list_remove(&it);
        }
        it.destroy(&it);

        sk_list_append(dest, poly);
        retval = true;
        goto cleanup;
    }

    // If source is entirely outside the clipping polygon, determine whether the clipping polygon is inside source
    if (!found_in)
    {
        sk_list_begin(&A_it, &clipping_polygon.geometry.polygon.points);
        while (A_it.has_next(&A_it))
        {
            if (is_inside(A_it.next(&A_it), source))
            {
                found_in = true;
                break;
            }

            break;
        }
        A_it.destroy(&A_it);

        // Clipping polygon is inside source. Source becomes clipping polygon.
        if (found_in)
        {
            sk_cg_geometry *poly = ALLOC(*poly, 1);
            poly->type = POLYGON;

            sk_iterator it;
            sk_list_begin(&it, &clipping_polygon.geometry.polygon.points);
            while (it.has_next(&it))
            {
                sk_cg_point *point = ALLOC(*point, 1);
                sk_cg_point *old_point = it.next(&it);
                *point = *old_point;
                sk_list_append(&poly->geometry.polygon.points, point);
            }
            it.destroy(&it);

            sk_list_append(dest, poly);
            retval = true;
            goto cleanup;
        }
        else
        {
            retval = false;
            goto cleanup;
        }
    }


    sk_cg_point intersection_point;
    w_a_node *intersection_node;
    w_a_node *B_node;
    bool B_end;
    w_a_node *A_node;
    bool A_end;

    // Loop across polygon B until no new intersection points with A have been found
    for (B_node = B_head, B_end = false; (!B_end || B_node != B_head); B_node = B_node->B_next)
    {
        B_end = true;

        // Loop across polygon A searching for a new intersection point
        for (A_node = A_head, A_end = false; (!A_end || A_node != A_head); A_node = A_node->A_next)
        {
            A_end = true;

            // If we're starting on an intersection point, don't try to intersect with itself
            if (B_node->A_next && B_node->B_next)
            {
                if (sk_cg_point_equals(B_node->point, A_node->point)
                        || sk_cg_point_equals(B_node->point, A_node->A_next->point))
                {
                    continue;
                }
            }

            // If we're ending on an intersection point don't try to intersect with itself
            if (B_node->B_next->A_next && B_node->B_next->B_next)
            {
                if (sk_cg_point_equals(B_node->B_next->point, A_node->point)
                        || sk_cg_point_equals(B_node->B_next->point, A_node->A_next->point))
                {
                    continue;
                }
            }

            // Find the intersection between the current line segments for polygons A and B
            if (intersection(B_node->point,
                                B_node->B_next->point,
                                A_node->point,
                                A_node->A_next->point,
                                &intersection_point))
            {
                intersection_node = ALLOC(*intersection_node, 1);
                intersection_node->point = ALLOC(*intersection_node->point, 1);
                *intersection_node->point = intersection_point;
                intersection_node->in = true;
                intersection_node->A_next = A_node->A_next;
                intersection_node->A_prev = A_node;
                intersection_node->B_next = B_node->B_next;
                intersection_node->B_prev = B_node;

                // If the head of either list will be replaced, point the head at the new intersection nodes
                if (sk_cg_point_equals(A_head->point, &intersection_point))
                {
                    A_head = intersection_node;
                }

                if (sk_cg_point_equals(B_head->point, &intersection_point))
                {
                    B_head = intersection_node;
                }

                // Update the W_A list for polygon A
                //  if intersected at the beginning vertex, replace it with intersection point
                //  if intersected at the ending vertex, replace it with intersection point
                if (sk_cg_point_equals(A_node->point, &intersection_point))
                {
                    intersection_node->A_prev = A_node->A_prev;

                    if (A_node->A_next && A_node->B_next)
                    {
                        free(A_node->point);
                    }
                    free(A_node);

                    A_node = intersection_node;
                }
                else if (sk_cg_point_equals(A_node->A_next->point, &intersection_point))
                {
                    intersection_node->A_next = A_node->A_next->A_next;

                    if (A_node->A_next->A_next && A_node->A_next->B_next)
                    {
                        free(A_node->A_next->point);
                    }
                    free(A_node->A_next);
                }

                // Update the W_A list for polygon B
                //  if intersected at the beginning vertex, replace it with intersection point
                //  if intersected at the ending vertex, replace it with intersection point
                if (sk_cg_point_equals(B_node->point, &intersection_point))
                {
                    intersection_node->B_prev = B_node->B_prev;

                    if (B_node->A_next && B_node->B_next)
                    {
                        free(B_node->point);
                    }
                    free(B_node);

                    B_node = intersection_node;
                }
                else if (sk_cg_point_equals(B_node->B_next->point, &intersection_point))
                {
                    intersection_node->B_next = B_node->B_next->B_next;

                    if (B_node->B_next->A_next && B_node->B_next->B_next)
                    {
                        free(B_node->B_next->point);
                    }
                    free(B_node->B_next);
                }

                // Update the intersection node's neighbors
                intersection_node->A_prev->A_next = intersection_node;
                intersection_node->A_next->A_prev = intersection_node;
                intersection_node->B_prev->B_next = intersection_node;
                intersection_node->B_next->B_prev = intersection_node;

                // Make the head of W_A list B point to this intersection node
                B_head = intersection_node;

                // Loop ends when we iterate over the entire polygon once without finding a new intersection point
                B_end = false;

                break;
            }
        }
    }


    w_a_node *node;
    // false = A, true = B

    // Iterate over polygon B until we don't find any more intersection nodes
    for (node = B_head, B_end = false; (!B_end || node != B_head);)
    {
        B_end = true;

        // Continue until we find an intersection node
        if (!(node->A_next && node->B_next))
        {
            node = node->B_next;
            continue;
        }

        // Node is an intersection node:
        sk_cg_geometry *polygon = ALLOC(*polygon, 1);
        polygon->type = POLYGON;
        sk_list_init(&polygon->geometry.polygon.points, NULL);

        // Remove intersection node, and all subsequent nodes until the next node is outside A.
        w_a_node *final_node = node;
        w_a_node *temp;
        while (final_node)
        {
            sk_cg_point *new_node = ALLOC(*new_node, 1);
            *new_node = *final_node->point;

            // Add this node's point to the new polygon, then remove this node from both lists.
            sk_list_append(&polygon->geometry.polygon.points, new_node);

            if (final_node->A_next && final_node->B_next)
            {
                free(final_node->point);
                final_node->point = NULL;
            }

            if (final_node->A_next)
            {
                if (final_node->A_next == final_node)
                {
                    A_head = NULL;
                }
                else
                {
                    if (A_head == final_node)
                    {
                        A_head = final_node->A_next;
                    }
                    final_node->A_next->A_prev = final_node->A_prev;
                    final_node->A_prev->A_next = final_node->A_next;
                }
            }
            if (final_node->B_next)
            {
                final_node->B_next->B_prev = final_node->B_prev;
                final_node->B_prev->B_next = final_node->B_next;
            }
            temp = final_node;

            if (final_node->B_next && (final_node->B_next->in || (final_node->B_next->A_next && final_node->B_next->B_next)))
            {
                final_node = final_node->B_next;
                node = final_node;
                B_head = node->B_next;
            }
            else if (final_node->B_prev && (final_node->B_prev->in || (final_node->B_prev->A_next && final_node->B_prev->B_next)))
            {
                final_node = final_node->B_prev;
                node = final_node;
                B_head = node->B_next;;
            }
            else if ((final_node->A_next) && final_node->A_next->in)
            {
                final_node = final_node->A_next;
            }
            else if ((final_node->A_prev) && final_node->A_prev->in)
            {
                final_node = final_node->A_prev;
            }
            else
            {
                if (final_node->B_prev)
                {
                    node = final_node->B_prev;
                    B_head = node->B_next;
                }
                B_end = false;
                final_node = NULL;
            }

            free(temp);
        }

        sk_list_append(dest, polygon);
        node = node->B_next;
    }

cleanup:

    {
        w_a_node *B_node;

        for (B_node = B_head->B_prev; B_node != B_head;)
        {
            B_node = B_node->B_prev;
            free(B_node->B_next);
        }
        free(B_node);
    }
B_W_A_list_fail:

    {
        w_a_node *A_node;

        if (A_head)
        {
            for (A_node = A_head->A_prev; A_node != A_head;)
            {
                A_node = A_node->A_prev;
                free(A_node->A_next);
            }
            free(A_node);
        }
    }
A_W_A_list_fail:

    sk_list_destroy(&clipping_polygon.geometry.polygon.points);
clipping_poly_init_fail:

    if (!retval)
    {
        sk_list_destroy(dest);
    }
dest_init_fail:

    return retval;
}
Esempio n. 4
0
bool parse_cg_polygon(sk_str *source, sk_cg_geometry *buffer)
{
    if (!source || !buffer)
    {
        return false;
    }

    bool retval = true;
    char delimiter = ' ';

    sk_iterator tokens;
    if (!sk_str_split(&tokens, source, delimiter))
    {
        retval = false;
        goto str_split_fail;
    }

    if (!sk_list_init(&buffer->geometry.polygon.points, NULL))
    {
        retval = false;
        goto list_init_fail;
    }

    char *token;
    sk_str str_token;
    SINT_64 x_coord;
    SINT_64 y_coord;
    while (tokens.has_next(&tokens))
    {
        token = tokens.next(&tokens);

        if (!tokens.has_next(&tokens))
        {
            retval = false;
            goto parse_point_fail;
        }

        sk_str_init(&str_token, token, 8);

        if (!parse_long(&str_token, 0, &x_coord))
        {
            retval = false;
            sk_str_destroy(&str_token);
            goto parse_point_fail;
        }

        sk_str_destroy(&str_token);

        token = tokens.next(&tokens);

        sk_str_init(&str_token, token, 8);

        if (!parse_long(&str_token, 0, &y_coord))
        {
            retval = false;
            sk_str_destroy(&str_token);
            goto parse_point_fail;
        }

        sk_str_destroy(&str_token);

        sk_cg_point *point = ALLOC(*point, 1);
        point->x = x_coord;
        point->y = y_coord;
        sk_list_append(&buffer->geometry.polygon.points, point);
    }

    sk_cg_point *first = sk_list_pop_head(&buffer->geometry.polygon.points);
    sk_cg_point *last = sk_list_pop_tail(&buffer->geometry.polygon.points);
    if (!sk_cg_point_equals(first, last))
    {
        retval = false;
        goto parse_point_fail;
    }
    sk_list_prepend(&buffer->geometry.polygon.points, first);

    buffer->type = POLYGON;

parse_point_fail:

    if (!retval)
    {
        sk_iterator it;
        sk_list_begin(&it, &buffer->geometry.polygon.points);
        while(it.has_next(&it))
        {
            free(it.next(&it));
        }

        sk_list_destroy(&buffer->geometry.polygon.points);
    }
list_init_fail:

    tokens.destroy(&tokens);
str_split_fail:

    return retval;
}
Esempio n. 5
0
bool scan_fill_cg_polygon
(
    sk_cg_geometry *source,
    pixel **framebuffer
)
{
    if (!source || POLYGON != source->type || !framebuffer)
    {
        return false;
    }

    // Convert polygon into list of lines
    sk_list poly_lines;
    sk_list_init(&poly_lines, NULL);

    sk_cg_point *a;
    sk_cg_point *b;
    sk_cg_point *first;
    sk_cg_point *line;

    sk_iterator it;
    sk_list_begin(&it, &source->geometry.polygon.points);

    a = it.next(&it);
    first = a;

    while (it.has_next(&it))
    {
        b = it.next(&it);
        line = ALLOC(*line, 2);
        line[0] = *a;
        line[1] = *b;

        sk_list_append(&poly_lines, line);

        a = b;
    }
    it.destroy(&it);
    line = ALLOC(*line, 2);
    line[0] = *a;
    line[1] = *first;

    sk_list_append(&poly_lines, line);




    // Determine minimum and maximum y axes, to instantiate scan line list
    int y_min = 0;
    int y_max = 0;

    // Also determine x_min and x_max to create concrete scan lines later on
    int x_min = 0;
    int x_max = 0;

    sk_cg_point *p;
    sk_list_begin(&it, &source->geometry.polygon.points);
    p = it.next(&it);
    y_min = p->y;
    y_max = p->y;
    x_min = p->x;
    x_max = p->x;
    while (it.has_next(&it))
    {
        p = it.next(&it);
        y_min = (p->y < y_min) ? p->y : y_min;
        y_max = (p->y > y_max) ? p->y : y_max;

        x_min = (p->x < x_min) ? p->x : x_min;
        x_max = (p->x > x_max) ? p->x : x_max;
    }
    it.destroy(&it);



    // Create a list for each scan line this polygon intersects : [y_min, y_max)
    sk_list *scan_lines = ALLOC(*scan_lines, y_max - y_min);

    int i;
    for (i = 0; i < y_max - y_min; ++i)
    {
        sk_list_init(&scan_lines[i], NULL);
    }

    // For each polygon edge, add it to each scan line which intersects that edge
    sk_list_begin(&it, &poly_lines);
    while (it.has_next(&it))
    {
        line = it.next(&it);

        if (line[0].y == line[1].y)
        {
            continue;
        }
        else if (line[0].y < line[1].y)
        {
            for (i = line[0].y; i < line[1].y; ++i)
            {
                sk_list_append(&scan_lines[i - y_min], line);
            }
        }
        else
        {
            for (i = line[0].y - 1; i >= line[1].y; --i)
            {
                sk_list_append(&scan_lines[i - y_min], line);
            }
        }
    }
    it.destroy(&it);


    // Convert each scan line list into a list of intersection points, sorted by x coordinate
    sk_cg_point *intersection_point;
    sk_cg_point scan_min =
    {
        .x = x_min - 1,
        .y = 0
    };
    sk_cg_point scan_max =
    {
        .x = x_max + 1,
        .y = 0
    };
    sk_list temp;
    sk_list_init(&temp, NULL);
    sk_iterator temp_it;

    for (i = 0; i < y_max - y_min; ++i)
    {
        scan_min.y = i + y_min;
        scan_max.y = i + y_min;

        sk_list_begin(&it, &scan_lines[i]);
        while (it.has_next(&it))
        {
            line = it.next(&it);

            // Calculate the intersection of this edge with the scan line
            intersection_point = ALLOC(*intersection_point, 1);
            if (!intersection(line, line + 1, &scan_min, &scan_max, intersection_point))
            {
                // FIXME error here
            }

            // We no longer need this edge
            sk_list_remove(&it);

            // Insert this point into our new list of intersections
            sk_list_begin(&temp_it, &temp);
            if (temp_it.has_next(&temp_it))
            {
                while (temp_it.has_next(&temp_it))
                {
                    p = temp_it.next(&temp_it);

                    if (intersection_point->x < p->x)
                    {
                        sk_list_pre_insert(&temp_it, intersection_point);
                        break;
                    }
                    if (!temp_it.has_next(&temp_it))
                    {
                        sk_list_append(&temp, intersection_point);
                        break;
                    }
                }
            }
            else
            {
                sk_list_append(&temp, intersection_point);
            }
            temp_it.destroy(&temp_it);
        }
        it.destroy(&it);

        sk_list_begin(&temp_it, &temp);
        while (temp_it.has_next(&temp_it))
        {
            sk_list_append(&scan_lines[i], temp_it.next(&temp_it));
            sk_list_remove(&temp_it);
        }
        temp_it.destroy(&temp_it);
    }
    sk_list_destroy(&temp);

    int x;
    for (i = 0; i < y_max - y_min; ++i)
    {
        sk_list_begin(&it, &scan_lines[i]);
        if (!it.has_next(&it))
        {
            it.destroy(&it);
            continue;
        }
        while (it.has_next(&it))
        {
            a = it.next(&it);
            b = it.next(&it);
            for (x = a->x; x < b->x; ++x)
            {
                framebuffer[a->y][x] = 1;
            }
        }
        it.destroy(&it);
    }

    // Destroy polygon line list
    sk_list_begin(&it, &poly_lines);
    while(it.has_next(&it))
    {
        free(it.next(&it));
    }
    it.destroy(&it);
    sk_list_destroy(&poly_lines);

    for (i = 0; i < y_max - y_min; ++i)
    {
        sk_list_destroy(&scan_lines[i]);
    }
    free(scan_lines);

    return true;
}

bool clip_x
(
    sk_cg_point *a,
    sk_cg_point *b,
    sk_cg_point *dest,
    int x
)
{
    if (!a || !b || !dest)
    {
        return false;
    }

    SINT_64 x_c;
    SINT_64 y_c;

    x_c = x;
    y_c = (((double)abs((x - a->x)) / (double)abs((b->x - a->x))) * abs((b->y - a->y)));

    if (b->y < a->y)
    {
        y_c -= a->y;
        y_c = -y_c;
    }
    else
    {
        y_c += a->y;
    }

    dest->x = x_c;
    dest->y = y_c;

    return true;
}

bool clip_y
(
    sk_cg_point *a,
    sk_cg_point *b,
    sk_cg_point *dest,
    int y
)
{
    if (!a || !b || !dest)
    {
        return false;
    }

    SINT_64 x_c;
    SINT_64 y_c;

    y_c = y;
    x_c = (((double)abs((b->x - a->x)) / (double)abs((b->y - a->y))) * abs((y - a->y)));

    if (b->x < a->x)
    {
        x_c -= a->x;
        x_c = -x_c;
    }
    else
    {
        x_c += a->x;
    }

    dest->x = x_c;
    dest->y = y_c;

    return true;
}

bool intersection
(
    sk_cg_point *a1,
    sk_cg_point *b1,
    sk_cg_point *a2,
    sk_cg_point *b2,
    sk_cg_point *dest
)
{
    // Edge 0: (a1, b1)
    // Edge 2: (a2, b2)
    // E_0 = a1 + t_0 * (b1 - a1)
    //                  (D0)
    // E_2 = a2 + t_2 * (b2 - a2)
    //                  (D2)
    //
    // a1x + t1 * d1x = a2x + t2 * d2x
    // a1y + t1 * d1y = a2y + t2 * d2y
    //
    // t1 = (a2x - a1x) + (t2 * d2x) / d1x
    //
    // a1y + ((a2y - a1x) + (t2 * d2x)) / d1x * d1y = a2y + t2 * d2y
    // ((a2x - a1x) + (t2 * d2x)) / d1x = ((a2y - a1y) + (t2 * d2y)) / d1y
    //
    // d1y (a2x - a1x) + d1y * d2x * t2 = d1x (a2y - a1y) + d1x *d2y * t2
    //
    // (d1x * d2y * t2) - (d1y * d2x * t2) = d1y (a2x - a1x) - d1x (a2y - a1y)
    //
    // t2 = d1y (a2x - a1x) - d1x (a2y - a1y)
    //      ---------------------------------
    //          (d1x * d2y) - (d1y * d2x)
    //
    //
    // t2 = (a1y - a2y) + (t1 * d1y) / d2y
    //
    // a1x + t1 * d1x = a2x + (d2x / d2y) ((a1y - a2y) + (t1 * d1y))
    //
    // d2y ((a1x - a2x) + (t1 * d1x)) = d2x ((a1y - a2y) + (t1 * d1y))
    //
    // d2y (a1x - a2x) + t1 (d1x * d2y) = d2x (a1y - a2y) + t1 (d1y * d2x)
    //
    // t1 = d2x (a1y - a2y) - d2y (a1x - a2x)
    //      ---------------------------------
    //          (d1x * d2y) - (d1y * d2x)
    //
    // t1 = d2y (a2x - a1x) - d2x (a2y - a1y)
    //      ---------------------------------
    //           (d1x * d2y) - (d1y * d2x)


    // Quantities:
    // d1x
    // d1y
    // d2x
    // d2y
    // A (a2x - a1x) * { d1y, d2y }
    // B (a2y - a1y) * { d1x, d2x }
    // C (d1x * d2y) - (d1y * d2x)

    if (!a1 || !b1 || !a2 || !b2|| !dest)
    {
        return false;
    }

    SINT_64 d1x = b1->x - a1->x;
    SINT_64 d1y = b1->y - a1->y;
    SINT_64 d2x = b2->x - a2->x;
    SINT_64 d2y = b2->y - a2->y;
    SINT_64 A, B;
    SINT_64 Ad1y, Ad2y;
    SINT_64 Bd1x, Bd2x;
    SINT_64 C = (d1x * d2y) - (d1y * d2x);
    double t1;
    double t2;

    if (!C)
    {
        return false;
    }

    A = a2->x - a1->x;
    B = a2->y - a1->y;
    Ad1y = A * d1y;
    Ad2y = A * d2y;
    Bd1x = B * d1x;
    Bd2x = B * d2x;
    t1 = (Ad2y - Bd2x) / (double)C;
    t2 = (Ad1y - Bd1x) / (double)C;

    if (t1 < 0 || t1 > 1 || t2 < 0 || t2 > 1)
    {
        return false;
    }

    dest->x = a1->x + t1 * d1x;
    dest->y = a1->y + t1 * d1y;

    return true;
}

bool is_inside
(
    sk_cg_point *source,
    sk_cg_geometry *target
)
{
    if (!source || !target || POLYGON != target->type)
    {
        return false;
    }

    SINT_64 min_x = 0;

    sk_iterator it;
    sk_list_begin(&it, &target->geometry.polygon.points);
    sk_cg_point *element = NULL;

    if (!it.has_next(&it))
    {
        it.destroy(&it);
        return false;
    }

    while (it.has_next(&it))
    {
        element = it.next(&it);
        min_x = (element->x < min_x) ? element->x : min_x;
    }
    it.destroy(&it);

    sk_cg_point outside =
    {
        .x = min_x - 1,
        .y = 0
    };
    sk_cg_point intersect_point;

    int num_intersections = 0;
    sk_list_begin(&it, &target->geometry.polygon.points);
    sk_cg_point *first = it.next(&it);
    sk_cg_point *A = first;
    sk_cg_point *B = NULL;
    bool intersected_first = false;
    bool intersected_B = false;
    while (it.has_next(&it))
    {
        B = it.next(&it);
        if (intersection(source, &outside, A, B, &intersect_point))
        {

            if (sk_cg_point_equals(&intersect_point, A))
            {
                if ((A == first))
                {
                    intersected_first = true;
                }

                if (intersected_B)
                {
                    --num_intersections;
                }
            }

            intersected_B = sk_cg_point_equals(&intersect_point, B);

            ++num_intersections;
        }

        A = B;
    }

    if (intersection(source, &outside, A, first, &intersect_point))
    {
        if  (  !(intersected_B && sk_cg_point_equals(&intersect_point, A))
            && !(intersected_first && sk_cg_point_equals(&intersect_point, first))
            )
        {
            ++num_intersections;
        }
    }

    it.destroy(&it);

    return (num_intersections & 0x1);
}
Esempio n. 6
0
skO *skO_parse (char **next, jmp_buf jmp, char *delim)
{
	skO     *obj;                       /* parsed token (or NULL)       */
	skO     *list     = skO_list_new(); /* used to store parsed objects */
	skO     *prefixed = NULL;           /* store "prefix sugar" tokens  */
	char    *src      = *next;
	jmp_buf pe;
	int     ended     = 0;

	consume_leading(&src);

	if (setjmp(pe)) {
		if (prefixed)
			free(prefixed);
		skO_free(list);
		printf("parse jmp\n");
	}

	if (delim) {
		if (*src != delim[0])
			return NULL;
		src++;
		consume_leading(&src);
		#ifdef SK_PARSER_DEBUG
		printf("Parsed %c\n", delim[0]);
		#endif
	} else if (*src == 0) {
		ended = 1;
		exit(EXIT_FAILURE);
	}

	while (!ended) {
		consume_leading(&src);

		if (*src == 0) {
			ended = 1;
			*next = src;
			break;
		}

		/* Handle end of lists and prefixed syntax. */

		if (delim) {
			if (*src == delim[1]) {
				src++;
				*next = src;
				#ifdef SK_PARSER_DEBUG
				printf("Parsed %c\n", delim[1]);
				#endif
				return list;
			}
		}

		/* Handle "prefix style" syntactic sugar. */

		prefixed = skO_parse(&src, pe, "()");
		if (prefixed)
			consume_leading(&src);

		/* Handle "reserving operations" syntactic sugar. */

		obj = parse_op_def(&src);
		if (obj) {
			sk_list_append(list, obj);
			obj = skO_symbol_new("$=>");
			goto matched;
		}

		obj = parse_obj_reserve(&src);
		if (obj) {
			sk_list_append(list, obj);
			obj = skO_symbol_new("$->");
			goto matched;
		}

		obj = parse_obj_restore(&src);
		if (obj) {
			sk_list_append(list, obj);
			obj = skO_symbol_new("$<-");
			goto matched;
		}

		/* Handle regular tokens. */

		if ((obj = parse_string_literal(&src, pe))
			|| (obj = parse_number(&src))
			|| (obj = parse_qidentifier(&src))
			|| (obj = parse_identifier(&src))
			|| (obj = parse_character_literal(&src, pe))
			|| (obj = skO_parse(&src, pe, "[]")))
			goto matched;

		/* If everything failed... */

		fprintf(stderr, "PANIC! Parsing error: %s\n", src);
		longjmp(jmp, 1);

	matched:
		sk_list_append(list, obj);
		
		if (prefixed) {
			sk_list_append(list, prefixed->data.list);
			free(prefixed);
			prefixed = NULL;
		}
	}

	*next = src;
	return list;
}
Esempio n. 7
0
bool clip_cg_bezier
(
    sk_cg_geometry *source,
    double increment,
    int x_min,
    int y_min,
    int x_max,
    int y_max,
    sk_list *dest
)
{
    if (!source || BEZIER != source->type || !dest || increment <= 0 || increment > 1)
    {
        if (dest)
        {
            sk_list_init(dest, NULL);
        }

        return false;
    }

    sk_list_init(dest, NULL);

    sk_cg_point P[4];
    sk_cg_point *p = P;
    sk_cg_point *next;

    sk_iterator it;
    sk_list_begin(&it, &source->geometry.bezier.control_points);
    while (it.has_next(&it))
    {
        next = it.next(&it);
        p->x = next->x;
        p->y = next->y;
        p++;
    }
    it.destroy(&it);

    sk_cg_point A, B;
    A = P[0];
    double t;
    for (t = increment; t < 1; t += increment)
    {
        double t2 = t * t;
        double t3 = t2 * t;
        double nt = 1 - t;
        double nt2 = nt * nt;
        double nt3 = nt2 * nt;

        B.x = (nt3 * P[0].x) + (3 * t * nt2 * P[1].x) + (3 * t2 * nt * P[2].x) + (t3 * P[3].x);
        B.y = (nt3 * P[0].y) + (3 * t * nt2 * P[1].y) + (3 * t2 * nt * P[2].y) + (t3 * P[3].y);

        sk_cg_geometry *line = ALLOC(*line, 1);
        line->type = LINE;
        line->geometry.line.a = A;
        line->geometry.line.b = B;

        sk_list_append(dest, line);

        A = B;
    }

    t = 1;
    double t2 = t * t;
    double t3 = t2 * t;
    double nt = 1 - t;
    double nt2 = nt * nt;
    double nt3 = nt2 * nt;

    B.x = roundf((nt3 * P[0].x) + (3 * t * nt2 * P[1].x) + (3 * t2 * nt * P[2].x) + (t3 * P[3].x));
    B.y = roundf((nt3 * P[0].y) + (3 * t * nt2 * P[1].y) + (3 * t2 * nt * P[2].y) + (t3 * P[3].y));

    sk_cg_geometry *line = ALLOC(*line, 1);
    line->type = LINE;
    line->geometry.line.a = A;
    line->geometry.line.b = B;

    sk_list_append(dest, line);

    sk_cg_geometry *g;
    sk_list_begin(&it, dest);
    while (it.has_next(&it))
    {
        g = it.next(&it);
        if (!clip_cg_line(g, x_min, y_min, x_max, y_max))
        {
            sk_list_remove(&it);
            sk_cg_geometry_destroy(g);
            free(g);
        }
    }

    return true;
}