/* graphene-quad.c: Quad
*
* Copyright 2014 Emmanuele Bassi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* SECTION:graphene-quad
* @title: Quad
* @short_description: Four-vertex quadrilateral
*
* A #graphene_quad_t represents a coplanar, four vertex quadrilateral shape.
*/
#include "graphene-private.h"
#include "graphene-quad.h"
#include "graphene-line-segment-private.h"
#include "graphene-rect.h"
#include "graphene-simd4f.h"
#include
/**
* graphene_quad_alloc: (constructor)
*
* Allocates a new #graphene_quad_t instance.
*
* The contents of the returned instance are undefined.
*
* Returns: (transfer full): the newly created #graphene_quad_t instance
*
* Since: 1.0
*/
graphene_quad_t *
graphene_quad_alloc (void)
{
return calloc (1, sizeof (graphene_quad_t));
}
/**
* graphene_quad_free:
* @q: a #graphene_quad_t
*
* Frees the resources allocated by graphene_quad_alloc()
*
* Since: 1.0
*/
void
graphene_quad_free (graphene_quad_t *q)
{
free (q);
}
/**
* graphene_quad_init:
* @q: the #graphene_quad_t to initialize
* @p1: the first point of the quadrilateral
* @p2: the second point of the quadrilateral
* @p3: the third point of the quadrilateral
* @p4: the fourth point of the quadrilateral
*
* Initializes a #graphene_quad_t with the given points.
*
* Returns: (transfer none): the initialized #graphene_quad_t
*
* Since: 1.0
*/
graphene_quad_t *
graphene_quad_init (graphene_quad_t *q,
const graphene_point_t *p1,
const graphene_point_t *p2,
const graphene_point_t *p3,
const graphene_point_t *p4)
{
q->points[0] = *p1;
q->points[1] = *p2;
q->points[2] = *p3;
q->points[3] = *p4;
return q;
}
/**
* graphene_quad_init_from_rect:
* @q: the #graphene_quad_t to initialize
* @r: a #graphene_rect_t
*
* Initializes a #graphene_quad_t using the four corners of the
* given #graphene_rect_t.
*
* Returns: (transfer none): the initialized #graphene_quad_t
*
* Since: 1.0
*/
graphene_quad_t *
graphene_quad_init_from_rect (graphene_quad_t *q,
const graphene_rect_t *r)
{
graphene_rect_get_top_left (r, &(q->points[0]));
graphene_rect_get_top_right (r, &(q->points[1]));
graphene_rect_get_bottom_right (r, &(q->points[2]));
graphene_rect_get_bottom_left (r, &(q->points[3]));
return q;
}
/**
* graphene_quad_init_from_points:
* @q: the #graphene_quad_t to initialize
* @points: (array fixed-size=4): an array of 4 #graphene_point_t
*
* Initializes a #graphene_quad_t using an array of points.
*
* Returns: (transfer none): the initialized #graphene_quad_t
*
* Since: 1.2
*/
graphene_quad_t *
graphene_quad_init_from_points (graphene_quad_t *q,
const graphene_point_t points[])
{
memcpy (q->points, points, sizeof (graphene_point_t) * 4);
return q;
}
/**
* graphene_quad_contains:
* @q: a #graphene_quad_t
* @p: a #graphene_point_t
*
* Checks if the given #graphene_quad_t contains the given #graphene_point_t.
*
* Returns: `true` if the point is inside the #graphene_quad_t
*
* Since: 1.0
*/
bool
graphene_quad_contains (const graphene_quad_t *q,
const graphene_point_t *p)
{
graphene_line_segment_t l1, l2, l3, l4;
l1 = graphene_line_segment_init (&q->points[0], &q->points[1]);
l2 = graphene_line_segment_init (&q->points[1], &q->points[2]);
l3 = graphene_line_segment_init (&q->points[2], &q->points[3]);
l4 = graphene_line_segment_init (&q->points[3], &q->points[0]);
return graphene_line_segment_points_on_same_side (l1, p, &(q->points[2])) &&
graphene_line_segment_points_on_same_side (l2, p, &(q->points[3])) &&
graphene_line_segment_points_on_same_side (l3, p, &(q->points[0])) &&
graphene_line_segment_points_on_same_side (l4, p, &(q->points[1]));
}
/**
* graphene_quad_bounds:
* @q: a #graphene_quad_t
* @r: (out caller-allocates): return location for a #graphene_rect_t
*
* Computes the bounding rectangle of @q and places it into @r.
*
* Since: 1.0
*/
void
graphene_quad_bounds (const graphene_quad_t *q,
graphene_rect_t *r)
{
graphene_simd4f_t vx, vy;
float min_x, max_x;
float min_y, max_y;
vx = graphene_simd4f_init (q->points[0].x, q->points[1].x, q->points[2].x, q->points[3].x);
vy = graphene_simd4f_init (q->points[0].y, q->points[1].y, q->points[2].y, q->points[3].y);
min_x = graphene_simd4f_get_x (graphene_simd4f_min_val (vx));
min_y = graphene_simd4f_get_x (graphene_simd4f_min_val (vy));
max_x = graphene_simd4f_get_x (graphene_simd4f_max_val (vx));
max_y = graphene_simd4f_get_x (graphene_simd4f_max_val (vy));
graphene_rect_init (r, min_x, min_y, max_x - min_x, max_y - min_y);
}
/**
* graphene_quad_get_point:
* @q: a #graphene_quad_t
* @index_: the index of the point to retrieve
*
* Retrieves the point of a #graphene_quad_t at the given index.
*
* Returns: (transfer none): a #graphene_point_t
*
* Since: 1.0
*/
const graphene_point_t *
graphene_quad_get_point (const graphene_quad_t *q,
unsigned int index_)
{
return &q->points[index_];
}