1 | /* graphene-quad.c: Quad |
2 | * |
3 | * SPDX-License-Identifier: MIT |
4 | * |
5 | * Copyright 2014 Emmanuele Bassi |
6 | * |
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
8 | * of this software and associated documentation files (the "Software"), to deal |
9 | * in the Software without restriction, including without limitation the rights |
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
11 | * copies of the Software, and to permit persons to whom the Software is |
12 | * furnished to do so, subject to the following conditions: |
13 | * |
14 | * The above copyright notice and this permission notice shall be included in |
15 | * all copies or substantial portions of the Software. |
16 | * |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
23 | * THE SOFTWARE. |
24 | */ |
25 | |
26 | /** |
27 | * SECTION:graphene-quad |
28 | * @title: Quad |
29 | * @short_description: Four-vertex quadrilateral |
30 | * |
31 | * A #graphene_quad_t represents a coplanar, four vertex quadrilateral shape. |
32 | */ |
33 | |
34 | #include "graphene-private.h" |
35 | |
36 | #include "graphene-quad.h" |
37 | |
38 | #include "graphene-line-segment-private.h" |
39 | #include "graphene-rect.h" |
40 | #include "graphene-simd4f.h" |
41 | |
42 | #include <string.h> |
43 | |
44 | /** |
45 | * graphene_quad_alloc: (constructor) |
46 | * |
47 | * Allocates a new #graphene_quad_t instance. |
48 | * |
49 | * The contents of the returned instance are undefined. |
50 | * |
51 | * Returns: (transfer full): the newly created #graphene_quad_t instance |
52 | * |
53 | * Since: 1.0 |
54 | */ |
55 | graphene_quad_t * |
56 | graphene_quad_alloc (void) |
57 | { |
58 | return calloc (nmemb: 1, size: sizeof (graphene_quad_t)); |
59 | } |
60 | |
61 | /** |
62 | * graphene_quad_free: |
63 | * @q: a #graphene_quad_t |
64 | * |
65 | * Frees the resources allocated by graphene_quad_alloc() |
66 | * |
67 | * Since: 1.0 |
68 | */ |
69 | void |
70 | graphene_quad_free (graphene_quad_t *q) |
71 | { |
72 | free (ptr: q); |
73 | } |
74 | |
75 | /** |
76 | * graphene_quad_init: |
77 | * @q: the #graphene_quad_t to initialize |
78 | * @p1: the first point of the quadrilateral |
79 | * @p2: the second point of the quadrilateral |
80 | * @p3: the third point of the quadrilateral |
81 | * @p4: the fourth point of the quadrilateral |
82 | * |
83 | * Initializes a #graphene_quad_t with the given points. |
84 | * |
85 | * Returns: (transfer none): the initialized #graphene_quad_t |
86 | * |
87 | * Since: 1.0 |
88 | */ |
89 | graphene_quad_t * |
90 | graphene_quad_init (graphene_quad_t *q, |
91 | const graphene_point_t *p1, |
92 | const graphene_point_t *p2, |
93 | const graphene_point_t *p3, |
94 | const graphene_point_t *p4) |
95 | { |
96 | q->points[0] = *p1; |
97 | q->points[1] = *p2; |
98 | q->points[2] = *p3; |
99 | q->points[3] = *p4; |
100 | |
101 | return q; |
102 | } |
103 | |
104 | /** |
105 | * graphene_quad_init_from_rect: |
106 | * @q: the #graphene_quad_t to initialize |
107 | * @r: a #graphene_rect_t |
108 | * |
109 | * Initializes a #graphene_quad_t using the four corners of the |
110 | * given #graphene_rect_t. |
111 | * |
112 | * Returns: (transfer none): the initialized #graphene_quad_t |
113 | * |
114 | * Since: 1.0 |
115 | */ |
116 | graphene_quad_t * |
117 | graphene_quad_init_from_rect (graphene_quad_t *q, |
118 | const graphene_rect_t *r) |
119 | { |
120 | graphene_rect_get_top_left (r, p: &(q->points[0])); |
121 | graphene_rect_get_top_right (r, p: &(q->points[1])); |
122 | graphene_rect_get_bottom_right (r, p: &(q->points[2])); |
123 | graphene_rect_get_bottom_left (r, p: &(q->points[3])); |
124 | |
125 | return q; |
126 | } |
127 | |
128 | /** |
129 | * graphene_quad_init_from_points: |
130 | * @q: the #graphene_quad_t to initialize |
131 | * @points: (array fixed-size=4): an array of 4 #graphene_point_t |
132 | * |
133 | * Initializes a #graphene_quad_t using an array of points. |
134 | * |
135 | * Returns: (transfer none): the initialized #graphene_quad_t |
136 | * |
137 | * Since: 1.2 |
138 | */ |
139 | graphene_quad_t * |
140 | graphene_quad_init_from_points (graphene_quad_t *q, |
141 | const graphene_point_t points[]) |
142 | { |
143 | memcpy (dest: q->points, src: points, n: sizeof (graphene_point_t) * 4); |
144 | |
145 | return q; |
146 | } |
147 | |
148 | /** |
149 | * graphene_quad_contains: |
150 | * @q: a #graphene_quad_t |
151 | * @p: a #graphene_point_t |
152 | * |
153 | * Checks if the given #graphene_quad_t contains the given #graphene_point_t. |
154 | * |
155 | * Returns: `true` if the point is inside the #graphene_quad_t |
156 | * |
157 | * Since: 1.0 |
158 | */ |
159 | bool |
160 | graphene_quad_contains (const graphene_quad_t *q, |
161 | const graphene_point_t *p) |
162 | { |
163 | graphene_line_segment_t l1, l2, l3, l4; |
164 | |
165 | l1 = graphene_line_segment_init (start: &q->points[0], end: &q->points[1]); |
166 | l2 = graphene_line_segment_init (start: &q->points[1], end: &q->points[2]); |
167 | l3 = graphene_line_segment_init (start: &q->points[2], end: &q->points[3]); |
168 | l4 = graphene_line_segment_init (start: &q->points[3], end: &q->points[0]); |
169 | |
170 | return graphene_line_segment_points_on_same_side (s: l1, a: p, b: &(q->points[2])) && |
171 | graphene_line_segment_points_on_same_side (s: l2, a: p, b: &(q->points[3])) && |
172 | graphene_line_segment_points_on_same_side (s: l3, a: p, b: &(q->points[0])) && |
173 | graphene_line_segment_points_on_same_side (s: l4, a: p, b: &(q->points[1])); |
174 | } |
175 | |
176 | /** |
177 | * graphene_quad_bounds: |
178 | * @q: a #graphene_quad_t |
179 | * @r: (out caller-allocates): return location for a #graphene_rect_t |
180 | * |
181 | * Computes the bounding rectangle of @q and places it into @r. |
182 | * |
183 | * Since: 1.0 |
184 | */ |
185 | void |
186 | graphene_quad_bounds (const graphene_quad_t *q, |
187 | graphene_rect_t *r) |
188 | { |
189 | graphene_simd4f_t vx, vy; |
190 | float min_x, max_x; |
191 | float min_y, max_y; |
192 | |
193 | vx = graphene_simd4f_init (q->points[0].x, q->points[1].x, q->points[2].x, q->points[3].x); |
194 | vy = graphene_simd4f_init (q->points[0].y, q->points[1].y, q->points[2].y, q->points[3].y); |
195 | |
196 | min_x = graphene_simd4f_get_x (graphene_simd4f_min_val (vx)); |
197 | min_y = graphene_simd4f_get_x (graphene_simd4f_min_val (vy)); |
198 | |
199 | max_x = graphene_simd4f_get_x (graphene_simd4f_max_val (vx)); |
200 | max_y = graphene_simd4f_get_x (graphene_simd4f_max_val (vy)); |
201 | |
202 | graphene_rect_init (r, x: min_x, y: min_y, width: max_x - min_x, height: max_y - min_y); |
203 | } |
204 | |
205 | /** |
206 | * graphene_quad_get_point: |
207 | * @q: a #graphene_quad_t |
208 | * @index_: the index of the point to retrieve |
209 | * |
210 | * Retrieves the point of a #graphene_quad_t at the given index. |
211 | * |
212 | * Returns: (transfer none): a #graphene_point_t |
213 | * |
214 | * Since: 1.0 |
215 | */ |
216 | const graphene_point_t * |
217 | graphene_quad_get_point (const graphene_quad_t *q, |
218 | unsigned int index_) |
219 | { |
220 | return &q->points[index_]; |
221 | } |
222 | |