@@ -201,30 +201,28 @@ _length_of_vector(double *vector)
201201}
202202
203203static PyObject *
204- _line_project_helper (pgLineBase * line , double * point , int do_clamp )
204+ _line_project_helper (pgLineBase * line , double * point , int clamp )
205205{
206206 // this is a vector that goes from one point of the line to another
207207 double line_vector [2 ] = {line -> bx - line -> ax , line -> by - line -> ay };
208- double line_length = _length_of_vector (line_vector );
209-
210- // this is a unit vector that points in the direction of the line
211- double normalized_line_vector [2 ] = {line_vector [0 ], line_vector [1 ]};
212- _normalize_vector (normalized_line_vector );
213208
214209 // this is a vector that goes from the start of the line to the point we
215210 // are projecting onto the line
216211 double vector_from_line_start_to_point [2 ] = {point [0 ] - line -> ax ,
217212 point [1 ] - line -> ay };
218213
219214 double dot_product =
220- vector_from_line_start_to_point [0 ] * normalized_line_vector [0 ] +
221- vector_from_line_start_to_point [1 ] * normalized_line_vector [1 ];
215+ (vector_from_line_start_to_point [0 ] * line_vector [0 ] +
216+ vector_from_line_start_to_point [1 ] * line_vector [1 ]) /
217+ (line_vector [0 ] * line_vector [0 ] + line_vector [1 ] * line_vector [1 ]);
222218
223- double projection [2 ] = {dot_product * normalized_line_vector [0 ],
224- dot_product * normalized_line_vector [1 ]};
219+ double projection [2 ] = {dot_product * line_vector [0 ],
220+ dot_product * line_vector [1 ]};
225221
226- if (do_clamp ) {
227- if (dot_product > line_length ) {
222+ if (clamp ) {
223+ if (projection [0 ] * projection [0 ] + projection [1 ] * projection [1 ] >
224+ line_vector [0 ] * line_vector [0 ] +
225+ line_vector [1 ] * line_vector [1 ]) {
228226 projection [0 ] = line_vector [0 ];
229227 projection [1 ] = line_vector [1 ];
230228 }
@@ -237,10 +235,8 @@ _line_project_helper(pgLineBase *line, double *point, int do_clamp)
237235 double projected_point [2 ] = {line -> ax + projection [0 ],
238236 line -> ay + projection [1 ]};
239237
240- PyObject * projected_tuple =
241- Py_BuildValue ("(dd)" , projected_point [0 ], projected_point [1 ]);
242-
243- return projected_tuple ;
238+ return pg_tuple_couple_from_values_double (projected_point [0 ],
239+ projected_point [1 ]);
244240}
245241
246242static PyObject *
@@ -284,47 +280,26 @@ pg_line_scale_ip(pgLineObject *self, PyObject *const *args, Py_ssize_t nargs)
284280}
285281
286282static PyObject *
287- pg_line_project (pgLineObject * self , PyObject * args , PyObject * kwnames )
283+ pg_line_project (pgLineObject * self , PyObject * const * args , Py_ssize_t nargs ,
284+ PyObject * kwnames )
288285{
289- PyObject * point_obj = NULL ;
290- int do_clamp = 0 ;
286+ double point [ 2 ] = { 0.f , 0.f } ;
287+ int clamp = 0 ;
291288
292- static char * kwlist [] = {"point" , "do_clamp" , NULL };
293-
294- if (!PyArg_ParseTupleAndKeywords (args , kwnames , "O|p:project" , kwlist ,
295- & point_obj , & do_clamp )) {
296- return RAISE (
297- PyExc_TypeError ,
298- "project requires a sequence(point) and an optional clamp flag" );
299- }
300-
301- PyObject * item ;
302- double point [2 ];
303-
304- if (!PySequence_Check (point_obj ) || PySequence_Size (point_obj ) != 2 ) {
305- return RAISE (
306- PyExc_ValueError ,
307- "project requires the point to be a sequence of 2 elements" );
308- }
309-
310- item = PySequence_GetItem (point_obj , 0 );
311- point [0 ] = PyFloat_AsDouble (item );
312-
313- PyObject * error_type ;
314- if ((error_type = PyErr_Occurred ())) {
315- return NULL ;
289+ if (nargs >= 1 ) {
290+ if (!pg_TwoDoublesFromObj (args [0 ], & point [0 ], & point [1 ])) {
291+ return RAISE (PyExc_TypeError ,
292+ "project requires a sequence of two numbers" );
293+ }
316294 }
317295
318- item = PySequence_GetItem (point_obj , 1 );
319- point [1 ] = PyFloat_AsDouble (item );
320-
321- if ((error_type = PyErr_Occurred ())) {
322- return NULL ;
296+ if (kwnames != NULL ) {
297+ clamp = PyObject_IsTrue (args [nargs ]);
323298 }
324299
325300 PyObject * projected_point ;
326301 if (!(projected_point =
327- _line_project_helper (& pgLine_AsLine (self ), point , do_clamp ))) {
302+ _line_project_helper (& pgLine_AsLine (self ), point , clamp ))) {
328303 return NULL ;
329304 }
330305
@@ -343,7 +318,7 @@ static struct PyMethodDef pg_line_methods[] = {
343318 {"scale" , (PyCFunction )pg_line_scale , METH_FASTCALL , DOC_LINE_SCALE },
344319 {"scale_ip" , (PyCFunction )pg_line_scale_ip , METH_FASTCALL ,
345320 DOC_LINE_SCALEIP },
346- {"project" , (PyCFunction )pg_line_project , METH_VARARGS | METH_KEYWORDS ,
321+ {"project" , (PyCFunction )pg_line_project , METH_FASTCALL | METH_KEYWORDS ,
347322 DOC_LINE_PROJECT },
348323 {NULL , NULL , 0 , NULL }};
349324
0 commit comments