11#include "doc/geometry_doc.h"
22#include "geometry_common.h"
33#include "methodobject.h"
4+ #include "pyerrors.h"
45#include "pytypedefs.h"
56
67static double
@@ -181,46 +182,6 @@ _line_scale_helper(pgLineBase *line, double factor, double origin)
181182 return 1 ;
182183}
183184
184- static PyObject *
185- _line_project_helper (pgLineBase * line , double * point , int clamp )
186- {
187- // this is a vector that goes from one point of the line to another
188- double line_vector [2 ] = {line -> bx - line -> ax , line -> by - line -> ay };
189-
190- // this is a vector that goes from the start of the line to the point we
191- // are projecting onto the line
192- double vector_from_line_start_to_point [2 ] = {point [0 ] - line -> ax ,
193- point [1 ] - line -> ay };
194-
195- double dot_product =
196- (vector_from_line_start_to_point [0 ] * line_vector [0 ] +
197- vector_from_line_start_to_point [1 ] * line_vector [1 ]) /
198- (line_vector [0 ] * line_vector [0 ] + line_vector [1 ] * line_vector [1 ]);
199-
200- double projection [2 ] = {dot_product * line_vector [0 ],
201- dot_product * line_vector [1 ]};
202-
203- if (clamp ) {
204- if (dot_product < 0 ) {
205- projection [0 ] = 0 ;
206- projection [1 ] = 0 ;
207- }
208- else if (projection [0 ] * projection [0 ] +
209- projection [1 ] * projection [1 ] >
210- line_vector [0 ] * line_vector [0 ] +
211- line_vector [1 ] * line_vector [1 ]) {
212- projection [0 ] = line_vector [0 ];
213- projection [1 ] = line_vector [1 ];
214- }
215- }
216-
217- double projected_point [2 ] = {line -> ax + projection [0 ],
218- line -> ay + projection [1 ]};
219-
220- return pg_tuple_couple_from_values_double (projected_point [0 ],
221- projected_point [1 ]);
222- }
223-
224185static PyObject *
225186pg_line_scale (pgLineObject * self , PyObject * const * args , Py_ssize_t nargs )
226187{
@@ -261,6 +222,61 @@ pg_line_scale_ip(pgLineObject *self, PyObject *const *args, Py_ssize_t nargs)
261222 Py_RETURN_NONE ;
262223}
263224
225+ static PyObject *
226+ _line_project_helper (pgLineBase * line , double * point , int clamp )
227+ {
228+ // this is a vector that goes from one point of the line to another
229+ double line_vector [2 ] = {line -> bx - line -> ax , line -> by - line -> ay };
230+ double squred_line_length =
231+ line_vector [0 ] * line_vector [0 ] + line_vector [1 ] * line_vector [1 ];
232+
233+ if (squred_line_length == 0.0 && clamp ) {
234+ double projected_point [2 ];
235+ projected_point [0 ] = line -> ax ;
236+ projected_point [1 ] = line -> ay ;
237+ return pg_tuple_couple_from_values_double (projected_point [0 ],
238+ projected_point [1 ]);
239+ }
240+ else if (squred_line_length == 0.0 ) {
241+ return RAISE (PyExc_ValueError ,
242+ "The Line has to have some length or this method has to "
243+ "be clamped to work" );
244+ }
245+
246+ // this is a vector that goes from the start of the line to the point we
247+ // are projecting onto the line
248+ double vector_from_line_start_to_point [2 ] = {point [0 ] - line -> ax ,
249+ point [1 ] - line -> ay };
250+
251+ double dot_product =
252+ (vector_from_line_start_to_point [0 ] * line_vector [0 ] +
253+ vector_from_line_start_to_point [1 ] * line_vector [1 ]) /
254+ (line_vector [0 ] * line_vector [0 ] + line_vector [1 ] * line_vector [1 ]);
255+
256+ double projection [2 ] = {dot_product * line_vector [0 ],
257+ dot_product * line_vector [1 ]};
258+
259+ if (clamp ) {
260+ if (dot_product < 0 ) {
261+ projection [0 ] = 0 ;
262+ projection [1 ] = 0 ;
263+ }
264+ else if (projection [0 ] * projection [0 ] +
265+ projection [1 ] * projection [1 ] >
266+ line_vector [0 ] * line_vector [0 ] +
267+ line_vector [1 ] * line_vector [1 ]) {
268+ projection [0 ] = line_vector [0 ];
269+ projection [1 ] = line_vector [1 ];
270+ }
271+ }
272+
273+ double projected_point [2 ] = {line -> ax + projection [0 ],
274+ line -> ay + projection [1 ]};
275+
276+ return pg_tuple_couple_from_values_double (projected_point [0 ],
277+ projected_point [1 ]);
278+ }
279+
264280static PyObject *
265281pg_line_project (pgLineObject * self , PyObject * args , PyObject * kwnames )
266282{
@@ -283,13 +299,7 @@ pg_line_project(pgLineObject *self, PyObject *args, PyObject *kwnames)
283299 "project requires a sequence of two numbers" );
284300 }
285301
286- PyObject * projected_point ;
287- if (!(projected_point =
288- _line_project_helper (& pgLine_AsLine (self ), point , clamp ))) {
289- return NULL ;
290- }
291-
292- return projected_point ;
302+ return _line_project_helper (& pgLine_AsLine (self ), point , clamp );
293303}
294304
295305static struct PyMethodDef pg_line_methods [] = {
0 commit comments