Generated by Cython 0.29.24
Yellow lines hint at Python interaction.
Click on a line that starts with a "+
" to see the C code that Cython generated for it.
Raw output: ec_real.c
001: # cython: boundscheck=False, wraparound=False, nonecheck=False, cdivision=True, optimize.use_switch=True
002: # encoding: utf-8
003: """
004: MIT License
005:
006: Copyright (c) 2019 Yoann Berenguer
007:
008: Permission is hereby granted, free of charge, to any person obtaining a copy
009: of this software and associated documentation files (the "Software"), to deal
010: in the Software without restriction, including without limitation the rights
011: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
012: copies of the Software, and to permit persons to whom the Software is
013: furnished to do so, subject to the following conditions:
014:
015: The above copyright notice and this permission notice shall be included in all
016: copies or substantial portions of the Software.
017:
018: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
021: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
023: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
024: SOFTWARE.
025:
026: """
027:
+028: import warnings
__pyx_t_1 = __Pyx_Import(__pyx_n_s_warnings, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_warnings, __pyx_t_1) < 0) __PYX_ERR(0, 28, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
029:
+030: warnings.filterwarnings("ignore", category=FutureWarning)
__Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_warnings); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_filterwarnings); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_category, __pyx_builtin_FutureWarning) < 0) __PYX_ERR(0, 30, __pyx_L1_error) __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__2, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; /* … */ __pyx_tuple__2 = PyTuple_Pack(1, __pyx_n_s_ignore); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(0, 30, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__2); __Pyx_GIVEREF(__pyx_tuple__2);
+031: warnings.filterwarnings("ignore", category=ImportWarning)
__Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_warnings); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 31, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_filterwarnings); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __pyx_t_3 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 31, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_category, __pyx_builtin_ImportWarning) < 0) __PYX_ERR(0, 31, __pyx_L1_error) __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__2, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 31, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
032:
+033: try:
{ /*try:*/ { /* … */ } __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; goto __pyx_L7_try_end; __pyx_L2_error:; __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; /* … */ __Pyx_XGIVEREF(__pyx_t_4); __Pyx_XGIVEREF(__pyx_t_5); __Pyx_XGIVEREF(__pyx_t_6); __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_5, __pyx_t_6); goto __pyx_L1_error; __pyx_L7_try_end:; }
+034: import pygame
__pyx_t_2 = __Pyx_Import(__pyx_n_s_pygame, 0, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 34, __pyx_L2_error) __Pyx_GOTREF(__pyx_t_2); if (PyDict_SetItem(__pyx_d, __pyx_n_s_pygame, __pyx_t_2) < 0) __PYX_ERR(0, 34, __pyx_L2_error) __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
035:
+036: except ImportError:
__pyx_t_7 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_ImportError); if (__pyx_t_7) { __Pyx_AddTraceback("ElasticCollision.ec_real", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_3, &__pyx_t_1) < 0) __PYX_ERR(0, 36, __pyx_L4_except_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_GOTREF(__pyx_t_3); __Pyx_GOTREF(__pyx_t_1);
+037: raise ImportError("\n<pygame> library is missing on your system."
__pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 37, __pyx_L4_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(0, 37, __pyx_L4_except_error) } goto __pyx_L4_except_error; __pyx_L4_except_error:; /* … */ __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_s_pygame_library_is_missing_on_yo); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 37, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple__3); __Pyx_GIVEREF(__pyx_tuple__3);
038: "\nTry: \n C:\\pip install pygame on a window command prompt.")
039:
+040: from pygame.math import Vector2
__pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_INCREF(__pyx_n_s_Vector2); __Pyx_GIVEREF(__pyx_n_s_Vector2); PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_Vector2); __pyx_t_3 = __Pyx_Import(__pyx_n_s_pygame_math, __pyx_t_1, -1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 40, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_Vector2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 40, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_Vector2, __pyx_t_1) < 0) __PYX_ERR(0, 40, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
041:
042: # Cython is require
+043: try:
{ /*try:*/ { /* … */ } }
044: cimport cython
045:
046: except ImportError:
047: raise ImportError("\n<cython> library is missing on your system."
048: "\nTry: \n C:\\pip install cython on a window command prompt.")
049:
050:
051: # Numpy is require
+052: try:
{ /*try:*/ { /* … */ } __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; goto __pyx_L21_try_end; __pyx_L16_error:; __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; /* … */ __Pyx_XGIVEREF(__pyx_t_4); __Pyx_XGIVEREF(__pyx_t_5); __Pyx_XGIVEREF(__pyx_t_6); __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_5, __pyx_t_6); goto __pyx_L1_error; __pyx_L21_try_end:; }
+053: import numpy
__pyx_t_3 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 53, __pyx_L16_error) __Pyx_GOTREF(__pyx_t_3); if (PyDict_SetItem(__pyx_d, __pyx_n_s_numpy, __pyx_t_3) < 0) __PYX_ERR(0, 53, __pyx_L16_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
054:
+055: except ImportError:
__pyx_t_7 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_ImportError); if (__pyx_t_7) { __Pyx_AddTraceback("ElasticCollision.ec_real", __pyx_clineno, __pyx_lineno, __pyx_filename); if (__Pyx_GetException(&__pyx_t_3, &__pyx_t_1, &__pyx_t_2) < 0) __PYX_ERR(0, 55, __pyx_L18_except_error) __Pyx_GOTREF(__pyx_t_3); __Pyx_GOTREF(__pyx_t_1); __Pyx_GOTREF(__pyx_t_2);
+056: raise ImportError("\n<numpy> library is missing on your system."
__pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 56, __pyx_L18_except_error) __Pyx_GOTREF(__pyx_t_8); __Pyx_Raise(__pyx_t_8, 0, 0, 0); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __PYX_ERR(0, 56, __pyx_L18_except_error) } goto __pyx_L18_except_error; __pyx_L18_except_error:;
057: "\nTry: \n C:\\pip install numpy on a window command prompt.")
058:
059: from libc.math cimport cos, sin, atan2, acos, sqrt
060:
061: cdef extern from '../Source/vector.c':
062:
063: struct vector2d:
064: float x
065: float y
066:
067: struct v_struct:
068: vector2d vector1
069: vector2d vector2
070:
071: void vecinit(vector2d *v, float x, float y)nogil
072: float vlength(vector2d *v)nogil
073: void scale_inplace(float c, vector2d *v)nogil
074: vector2d subcomponents(vector2d v1, vector2d v2)nogil
075: void scale_inplace(float c, vector2d *v)nogil
076: float dot(vector2d *v1, vector2d *v2)nogil
077:
078:
079: DEF M_PI = 3.14159265358979323846
080: DEF M_PI2 = 3.14159265358979323846 / 2.0
081:
082: # **************************** PYTHON INTERFACE ***************************************
083:
084: @cython.boundscheck(False)
085: @cython.wraparound(False)
086: @cython.nonecheck(False)
087: @cython.cdivision(True)
+088: cpdef tuple momentum_trigonometry_real(
static PyObject *__pyx_pw_16ElasticCollision_7ec_real_1momentum_trigonometry_real(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static PyObject *__pyx_f_16ElasticCollision_7ec_real_momentum_trigonometry_real(PyObject *__pyx_v_obj1_centre, PyObject *__pyx_v_obj2_centre, PyObject *__pyx_v_obj1_vector, PyObject *__pyx_v_obj2_vector, double __pyx_v_obj1_mass, double __pyx_v_obj2_mass, CYTHON_UNUSED int __pyx_skip_dispatch) { struct vector2d __pyx_v_vec1; struct vector2d __pyx_v_vec2; struct v_struct __pyx_v_collision; float __pyx_v_v1_x; float __pyx_v_v1_y; float __pyx_v_v2_x; float __pyx_v_v2_y; float __pyx_v_c1_x; float __pyx_v_c1_y; float __pyx_v_c2_x; float __pyx_v_c2_y; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("momentum_trigonometry_real", 0); /* … */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_XDECREF(__pyx_t_9); __Pyx_XDECREF(__pyx_t_11); __Pyx_XDECREF(__pyx_t_12); __Pyx_AddTraceback("ElasticCollision.ec_real.momentum_trigonometry_real", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* Python wrapper */ static PyObject *__pyx_pw_16ElasticCollision_7ec_real_1momentum_trigonometry_real(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static char __pyx_doc_16ElasticCollision_7ec_real_momentum_trigonometry_real[] = "\n RETURN VECTORS V1 & V2 AFTER OBJECT COLLISION (TRIGONOMETRY) \n \n This method is using trigonometric equations to determine the objects final velocities\n Refer to Two-dimensional collision with two moving objects in the following link : \n https://en.wikipedia.org/wiki/Elastic_collision \n \n * This method can be used to resolved 2d elastic collision in a cartesian system \n \n * obj1_vector & obj2_vector are un-normalized vectors in order to keep the total kinetic \n energy and to redistribute the force to the final velocities (v1 & v2) \n \n :param obj1_centre: Vector2; Centre of object 1. This vector is not normalized and the components x, y \n correspond to the object position on the screen \n :param obj2_centre: Vector2; Centre of object 2. This vector is not normalized and the components x, y \n correspond to the object position on the screen \n :param obj1_vector: Vector2; Object 1 direction vector, un-normalized 2d Vector\n If both vector direction are normalized the output will also be normalized.\n :param obj2_vector: Vector2; Object 2 direction vector, un-normalized 2d Vector\n If both vector direction are normalized the output will also be normalized. \n :param obj1_mass: float; Mass of object 1 in kg \n :param obj2_mass: float; Mass of object 2 in kg\n :return: Tuple containing v1 and v2 (object vectors after collision).\n "; static PyObject *__pyx_pw_16ElasticCollision_7ec_real_1momentum_trigonometry_real(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { PyObject *__pyx_v_obj1_centre = 0; PyObject *__pyx_v_obj2_centre = 0; PyObject *__pyx_v_obj1_vector = 0; PyObject *__pyx_v_obj2_vector = 0; double __pyx_v_obj1_mass; double __pyx_v_obj2_mass; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("momentum_trigonometry_real (wrapper)", 0); { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_obj1_centre,&__pyx_n_s_obj2_centre,&__pyx_n_s_obj1_vector,&__pyx_n_s_obj2_vector,&__pyx_n_s_obj1_mass,&__pyx_n_s_obj2_mass,0}; PyObject* values[6] = {0,0,0,0,0,0}; if (unlikely(__pyx_kwds)) { Py_ssize_t kw_args; const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); switch (pos_args) { case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); CYTHON_FALLTHROUGH; case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); CYTHON_FALLTHROUGH; case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); CYTHON_FALLTHROUGH; case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); CYTHON_FALLTHROUGH; case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } kw_args = PyDict_Size(__pyx_kwds); switch (pos_args) { case 0: if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj1_centre)) != 0)) kw_args--; else goto __pyx_L5_argtuple_error; CYTHON_FALLTHROUGH; case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj2_centre)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_trigonometry_real", 1, 6, 6, 1); __PYX_ERR(0, 88, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 2: if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj1_vector)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_trigonometry_real", 1, 6, 6, 2); __PYX_ERR(0, 88, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 3: if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj2_vector)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_trigonometry_real", 1, 6, 6, 3); __PYX_ERR(0, 88, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 4: if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj1_mass)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_trigonometry_real", 1, 6, 6, 4); __PYX_ERR(0, 88, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 5: if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj2_mass)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_trigonometry_real", 1, 6, 6, 5); __PYX_ERR(0, 88, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "momentum_trigonometry_real") < 0)) __PYX_ERR(0, 88, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 6) { goto __pyx_L5_argtuple_error; } else { values[0] = PyTuple_GET_ITEM(__pyx_args, 0); values[1] = PyTuple_GET_ITEM(__pyx_args, 1); values[2] = PyTuple_GET_ITEM(__pyx_args, 2); values[3] = PyTuple_GET_ITEM(__pyx_args, 3); values[4] = PyTuple_GET_ITEM(__pyx_args, 4); values[5] = PyTuple_GET_ITEM(__pyx_args, 5); } __pyx_v_obj1_centre = values[0]; __pyx_v_obj2_centre = values[1]; __pyx_v_obj1_vector = values[2]; __pyx_v_obj2_vector = values[3]; __pyx_v_obj1_mass = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_obj1_mass == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 93, __pyx_L3_error) __pyx_v_obj2_mass = __pyx_PyFloat_AsDouble(values[5]); if (unlikely((__pyx_v_obj2_mass == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 94, __pyx_L3_error) } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("momentum_trigonometry_real", 1, 6, 6, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 88, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("ElasticCollision.ec_real.momentum_trigonometry_real", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_16ElasticCollision_7ec_real_momentum_trigonometry_real(__pyx_self, __pyx_v_obj1_centre, __pyx_v_obj2_centre, __pyx_v_obj1_vector, __pyx_v_obj2_vector, __pyx_v_obj1_mass, __pyx_v_obj2_mass); int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyObject *__pyx_pf_16ElasticCollision_7ec_real_momentum_trigonometry_real(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_obj1_centre, PyObject *__pyx_v_obj2_centre, PyObject *__pyx_v_obj1_vector, PyObject *__pyx_v_obj2_vector, double __pyx_v_obj1_mass, double __pyx_v_obj2_mass) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("momentum_trigonometry_real", 0); __Pyx_XDECREF(__pyx_r); __pyx_t_1 = __pyx_f_16ElasticCollision_7ec_real_momentum_trigonometry_real(__pyx_v_obj1_centre, __pyx_v_obj2_centre, __pyx_v_obj1_vector, __pyx_v_obj2_vector, __pyx_v_obj1_mass, __pyx_v_obj2_mass, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 88, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("ElasticCollision.ec_real.momentum_trigonometry_real", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; }
089: obj1_centre : Vector2,
090: obj2_centre : Vector2,
091: obj1_vector : Vector2,
092: obj2_vector : Vector2,
093: obj1_mass : float,
094: obj2_mass : float
095: ):
096: """
097: RETURN VECTORS V1 & V2 AFTER OBJECT COLLISION (TRIGONOMETRY)
098:
099: This method is using trigonometric equations to determine the objects final velocities
100: Refer to Two-dimensional collision with two moving objects in the following link :
101: https://en.wikipedia.org/wiki/Elastic_collision
102:
103: * This method can be used to resolved 2d elastic collision in a cartesian system
104:
105: * obj1_vector & obj2_vector are un-normalized vectors in order to keep the total kinetic
106: energy and to redistribute the force to the final velocities (v1 & v2)
107:
108: :param obj1_centre: Vector2; Centre of object 1. This vector is not normalized and the components x, y
109: correspond to the object position on the screen
110: :param obj2_centre: Vector2; Centre of object 2. This vector is not normalized and the components x, y
111: correspond to the object position on the screen
112: :param obj1_vector: Vector2; Object 1 direction vector, un-normalized 2d Vector
113: If both vector direction are normalized the output will also be normalized.
114: :param obj2_vector: Vector2; Object 2 direction vector, un-normalized 2d Vector
115: If both vector direction are normalized the output will also be normalized.
116: :param obj1_mass: float; Mass of object 1 in kg
117: :param obj2_mass: float; Mass of object 2 in kg
118: :return: Tuple containing v1 and v2 (object vectors after collision).
119: """
120: cdef:
121: vector2d vec1, vec2
122: v_struct collision
123: float v1_x, v1_y, v2_x, v2_y
124: float c1_x, c1_y, c2_x, c2_y
125:
+126: v1_x, v1_y, v2_x, v2_y = obj1_vector.x, obj1_vector.y, obj2_vector.x, obj2_vector.y
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj1_vector, __pyx_n_s_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 126, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_2 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 126, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj1_vector, __pyx_n_s_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 126, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_3 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 126, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj2_vector, __pyx_n_s_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 126, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_4 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_4 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 126, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj2_vector, __pyx_n_s_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 126, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_5 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_5 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 126, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_v1_x = __pyx_t_2; __pyx_v_v1_y = __pyx_t_3; __pyx_v_v2_x = __pyx_t_4; __pyx_v_v2_y = __pyx_t_5;
+127: c1_x, c1_y, c2_x, c2_y = obj1_centre.x, obj1_centre.y, obj2_centre.x, obj2_centre.y
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj1_centre, __pyx_n_s_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 127, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_5 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_5 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 127, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj1_centre, __pyx_n_s_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 127, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_4 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_4 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 127, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj2_centre, __pyx_n_s_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 127, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_3 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 127, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj2_centre, __pyx_n_s_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 127, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_2 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 127, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_c1_x = __pyx_t_5; __pyx_v_c1_y = __pyx_t_4; __pyx_v_c2_x = __pyx_t_3; __pyx_v_c2_y = __pyx_t_2;
128:
+129: with nogil:
{ #ifdef WITH_THREAD PyThreadState *_save; Py_UNBLOCK_THREADS __Pyx_FastGIL_Remember(); #endif /*try:*/ { /* … */ /*finally:*/ { /*normal exit:*/{ #ifdef WITH_THREAD __Pyx_FastGIL_Forget(); Py_BLOCK_THREADS #endif goto __pyx_L5; } __pyx_L5:; } }
+130: vecinit(&vec1, v1_x, v1_y)
vecinit((&__pyx_v_vec1), __pyx_v_v1_x, __pyx_v_v1_y);
+131: vecinit(&vec2, v2_x, v2_y)
vecinit((&__pyx_v_vec2), __pyx_v_v2_x, __pyx_v_v2_y);
132: # DETERMINES V1 & V2 COMPONENTS AFTER COLLISION
133: collision = \
+134: get_momentum_trigonometry_vecR(
__pyx_v_collision = __pyx_f_16ElasticCollision_7ec_real_get_momentum_trigonometry_vecR(__pyx_v_c1_x, __pyx_v_c1_y, __pyx_v_c2_x, __pyx_v_c2_y, __pyx_v_vec1, __pyx_v_vec2, __pyx_v_obj1_mass, __pyx_v_obj2_mass); }
135: c1_x, c1_y, c2_x, c2_y,
136: vec1, vec2, obj1_mass, obj2_mass)
137:
+138: return Vector2(collision.vector1.x, collision.vector1.y), \
__Pyx_XDECREF(__pyx_r); __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_Vector2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 138, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __pyx_t_7 = PyFloat_FromDouble(__pyx_v_collision.vector1.x); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 138, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __pyx_t_8 = PyFloat_FromDouble(__pyx_v_collision.vector1.y); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 138, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); __pyx_t_9 = NULL; __pyx_t_10 = 0; if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) { __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_6); if (likely(__pyx_t_9)) { PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); __Pyx_INCREF(__pyx_t_9); __Pyx_INCREF(function); __Pyx_DECREF_SET(__pyx_t_6, function); __pyx_t_10 = 1; } } #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_7, __pyx_t_8}; __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 138, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; } else #endif #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_7, __pyx_t_8}; __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 138, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; } else #endif { __pyx_t_11 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 138, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_11); if (__pyx_t_9) { __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_9); __pyx_t_9 = NULL; } __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_11, 0+__pyx_t_10, __pyx_t_7); __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_11, 1+__pyx_t_10, __pyx_t_8); __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 138, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; } __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; /* … */ __pyx_t_11 = PyTuple_New(2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 138, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_11); __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_1); __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_11, 1, __pyx_t_6); __pyx_t_1 = 0; __pyx_t_6 = 0; __pyx_r = ((PyObject*)__pyx_t_11); __pyx_t_11 = 0; goto __pyx_L0;
+139: Vector2(collision.vector2.x, collision.vector2.y)
__Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_Vector2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_11); __pyx_t_8 = PyFloat_FromDouble(__pyx_v_collision.vector2.x); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); __pyx_t_7 = PyFloat_FromDouble(__pyx_v_collision.vector2.y); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __pyx_t_9 = NULL; __pyx_t_10 = 0; if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_11))) { __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_11); if (likely(__pyx_t_9)) { PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_11); __Pyx_INCREF(__pyx_t_9); __Pyx_INCREF(function); __Pyx_DECREF_SET(__pyx_t_11, function); __pyx_t_10 = 1; } } #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_11)) { PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_8, __pyx_t_7}; __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_11, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; } else #endif #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_11)) { PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_8, __pyx_t_7}; __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_11, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; } else #endif { __pyx_t_12 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_12); if (__pyx_t_9) { __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_9); __pyx_t_9 = NULL; } __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_12, 0+__pyx_t_10, __pyx_t_8); __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_12, 1+__pyx_t_10, __pyx_t_7); __pyx_t_8 = 0; __pyx_t_7 = 0; __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_11, __pyx_t_12, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; } __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
140:
141:
142: # **************************** ANGLE FREE **********************************************************
143:
144: @cython.boundscheck(False)
145: @cython.wraparound(False)
146: @cython.nonecheck(False)
147: @cython.cdivision(True)
+148: cpdef tuple momentum_angle_free_real(
static PyObject *__pyx_pw_16ElasticCollision_7ec_real_3momentum_angle_free_real(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static PyObject *__pyx_f_16ElasticCollision_7ec_real_momentum_angle_free_real(PyObject *__pyx_v_obj1_vector, PyObject *__pyx_v_obj2_vector, double __pyx_v_obj1_mass, double __pyx_v_obj2_mass, PyObject *__pyx_v_obj1_centre, PyObject *__pyx_v_obj2_centre, CYTHON_UNUSED int __pyx_skip_dispatch) { struct vector2d __pyx_v_vec1; struct vector2d __pyx_v_vec2; struct vector2d __pyx_v_x1_vec; struct vector2d __pyx_v_x2_vec; float __pyx_v_v1_x; float __pyx_v_v1_y; float __pyx_v_v2_x; float __pyx_v_v2_y; float __pyx_v_c1_x; float __pyx_v_c1_y; float __pyx_v_c2_x; float __pyx_v_c2_y; struct v_struct __pyx_v_v; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("momentum_angle_free_real", 0); /* … */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_6); __Pyx_XDECREF(__pyx_t_7); __Pyx_XDECREF(__pyx_t_8); __Pyx_XDECREF(__pyx_t_9); __Pyx_XDECREF(__pyx_t_11); __Pyx_XDECREF(__pyx_t_12); __Pyx_AddTraceback("ElasticCollision.ec_real.momentum_angle_free_real", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* Python wrapper */ static PyObject *__pyx_pw_16ElasticCollision_7ec_real_3momentum_angle_free_real(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static char __pyx_doc_16ElasticCollision_7ec_real_2momentum_angle_free_real[] = "\n RETURN VECTORS V1 & V2 AFTER OBJECT COLLISION (ANGLE FREE METHOD)\n \n This method is using angle free equations to determine the objects final velocities\n Refer to Two-dimensional collision with two moving objects in the following link : \n https://en.wikipedia.org/wiki/Elastic_collision \n \n * This method can be used to resolved 2d elastic collision in cartesian system coordinates\n \n * obj1_vector & obj2_vector are un-normalized vectors in order to keep the total kinetic \n energy and to redistribute the force to the final velocities (v1 & v2) \n \n :param obj1_centre: Vector2; Centre of object 1. This vector is not normalized and the components x, y \n correspond to the object position on the screen \n :param obj2_centre: Vector2; Centre of object 2. This vector is not normalized and the components x, y \n correspond to the object position on the screen \n :param obj1_vector: Vector2; Object 1 direction vector, un-normalized 2d Vector\n If both vector direction are normalized the output will also be normalized.\n :param obj2_vector: Vector2; Object 2 direction vector un-normalized 2d Vector\n If both vector direction are normalized the output will also be normalized. \n :param obj1_mass: float; Mass of object 1 in kg \n :param obj2_mass: float; Mass of object 2 in kg\n :return: Tuple containing v1 and v2 (object vectors after collision).\n "; static PyObject *__pyx_pw_16ElasticCollision_7ec_real_3momentum_angle_free_real(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { PyObject *__pyx_v_obj1_vector = 0; PyObject *__pyx_v_obj2_vector = 0; double __pyx_v_obj1_mass; double __pyx_v_obj2_mass; PyObject *__pyx_v_obj1_centre = 0; PyObject *__pyx_v_obj2_centre = 0; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("momentum_angle_free_real (wrapper)", 0); { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_obj1_vector,&__pyx_n_s_obj2_vector,&__pyx_n_s_obj1_mass,&__pyx_n_s_obj2_mass,&__pyx_n_s_obj1_centre,&__pyx_n_s_obj2_centre,0}; PyObject* values[6] = {0,0,0,0,0,0}; if (unlikely(__pyx_kwds)) { Py_ssize_t kw_args; const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); switch (pos_args) { case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); CYTHON_FALLTHROUGH; case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); CYTHON_FALLTHROUGH; case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); CYTHON_FALLTHROUGH; case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); CYTHON_FALLTHROUGH; case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } kw_args = PyDict_Size(__pyx_kwds); switch (pos_args) { case 0: if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj1_vector)) != 0)) kw_args--; else goto __pyx_L5_argtuple_error; CYTHON_FALLTHROUGH; case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj2_vector)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_angle_free_real", 1, 6, 6, 1); __PYX_ERR(0, 148, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 2: if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj1_mass)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_angle_free_real", 1, 6, 6, 2); __PYX_ERR(0, 148, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 3: if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj2_mass)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_angle_free_real", 1, 6, 6, 3); __PYX_ERR(0, 148, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 4: if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj1_centre)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_angle_free_real", 1, 6, 6, 4); __PYX_ERR(0, 148, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 5: if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj2_centre)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("momentum_angle_free_real", 1, 6, 6, 5); __PYX_ERR(0, 148, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "momentum_angle_free_real") < 0)) __PYX_ERR(0, 148, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 6) { goto __pyx_L5_argtuple_error; } else { values[0] = PyTuple_GET_ITEM(__pyx_args, 0); values[1] = PyTuple_GET_ITEM(__pyx_args, 1); values[2] = PyTuple_GET_ITEM(__pyx_args, 2); values[3] = PyTuple_GET_ITEM(__pyx_args, 3); values[4] = PyTuple_GET_ITEM(__pyx_args, 4); values[5] = PyTuple_GET_ITEM(__pyx_args, 5); } __pyx_v_obj1_vector = values[0]; __pyx_v_obj2_vector = values[1]; __pyx_v_obj1_mass = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_obj1_mass == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 151, __pyx_L3_error) __pyx_v_obj2_mass = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_obj2_mass == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 152, __pyx_L3_error) __pyx_v_obj1_centre = values[4]; __pyx_v_obj2_centre = values[5]; } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("momentum_angle_free_real", 1, 6, 6, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 148, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("ElasticCollision.ec_real.momentum_angle_free_real", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_16ElasticCollision_7ec_real_2momentum_angle_free_real(__pyx_self, __pyx_v_obj1_vector, __pyx_v_obj2_vector, __pyx_v_obj1_mass, __pyx_v_obj2_mass, __pyx_v_obj1_centre, __pyx_v_obj2_centre); int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyObject *__pyx_pf_16ElasticCollision_7ec_real_2momentum_angle_free_real(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_obj1_vector, PyObject *__pyx_v_obj2_vector, double __pyx_v_obj1_mass, double __pyx_v_obj2_mass, PyObject *__pyx_v_obj1_centre, PyObject *__pyx_v_obj2_centre) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("momentum_angle_free_real", 0); __Pyx_XDECREF(__pyx_r); __pyx_t_1 = __pyx_f_16ElasticCollision_7ec_real_momentum_angle_free_real(__pyx_v_obj1_vector, __pyx_v_obj2_vector, __pyx_v_obj1_mass, __pyx_v_obj2_mass, __pyx_v_obj1_centre, __pyx_v_obj2_centre, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 148, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("ElasticCollision.ec_real.momentum_angle_free_real", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; }
149: obj1_vector : Vector2,
150: obj2_vector : Vector2,
151: obj1_mass : float,
152: obj2_mass : float,
153: obj1_centre : Vector2,
154: obj2_centre : Vector2,
155: ):
156: """
157: RETURN VECTORS V1 & V2 AFTER OBJECT COLLISION (ANGLE FREE METHOD)
158:
159: This method is using angle free equations to determine the objects final velocities
160: Refer to Two-dimensional collision with two moving objects in the following link :
161: https://en.wikipedia.org/wiki/Elastic_collision
162:
163: * This method can be used to resolved 2d elastic collision in cartesian system coordinates
164:
165: * obj1_vector & obj2_vector are un-normalized vectors in order to keep the total kinetic
166: energy and to redistribute the force to the final velocities (v1 & v2)
167:
168: :param obj1_centre: Vector2; Centre of object 1. This vector is not normalized and the components x, y
169: correspond to the object position on the screen
170: :param obj2_centre: Vector2; Centre of object 2. This vector is not normalized and the components x, y
171: correspond to the object position on the screen
172: :param obj1_vector: Vector2; Object 1 direction vector, un-normalized 2d Vector
173: If both vector direction are normalized the output will also be normalized.
174: :param obj2_vector: Vector2; Object 2 direction vector un-normalized 2d Vector
175: If both vector direction are normalized the output will also be normalized.
176: :param obj1_mass: float; Mass of object 1 in kg
177: :param obj2_mass: float; Mass of object 2 in kg
178: :return: Tuple containing v1 and v2 (object vectors after collision).
179: """
180:
181: cdef:
182: vector2d vec1, vec2, x1_vec, x2_vec
183: float v1_x, v1_y, v2_x, v2_y
184: float c1_x, c1_y, c2_x, c2_y
185: v_struct v
186:
+187: v1_x, v1_y, v2_x, v2_y = obj1_vector.x, obj1_vector.y, obj2_vector.x, obj2_vector.y
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj1_vector, __pyx_n_s_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 187, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_2 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 187, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj1_vector, __pyx_n_s_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 187, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_3 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 187, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj2_vector, __pyx_n_s_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 187, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_4 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_4 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 187, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj2_vector, __pyx_n_s_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 187, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_5 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_5 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 187, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_v1_x = __pyx_t_2; __pyx_v_v1_y = __pyx_t_3; __pyx_v_v2_x = __pyx_t_4; __pyx_v_v2_y = __pyx_t_5;
+188: c1_x, c1_y, c2_x, c2_y = obj1_centre.x, obj1_centre.y, obj2_centre.x, obj2_centre.y
__pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj1_centre, __pyx_n_s_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_5 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_5 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 188, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj1_centre, __pyx_n_s_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_4 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_4 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 188, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj2_centre, __pyx_n_s_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_3 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 188, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj2_centre, __pyx_n_s_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_2 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 188, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_v_c1_x = __pyx_t_5; __pyx_v_c1_y = __pyx_t_4; __pyx_v_c2_x = __pyx_t_3; __pyx_v_c2_y = __pyx_t_2;
189:
+190: with nogil:
{ #ifdef WITH_THREAD PyThreadState *_save; Py_UNBLOCK_THREADS __Pyx_FastGIL_Remember(); #endif /*try:*/ { /* … */ /*finally:*/ { /*normal exit:*/{ #ifdef WITH_THREAD __Pyx_FastGIL_Forget(); Py_BLOCK_THREADS #endif goto __pyx_L5; } __pyx_L5:; } }
+191: vecinit(&vec1, v1_x, v1_y)
vecinit((&__pyx_v_vec1), __pyx_v_v1_x, __pyx_v_v1_y);
+192: vecinit(&vec2, v2_x, v2_y)
vecinit((&__pyx_v_vec2), __pyx_v_v2_x, __pyx_v_v2_y);
+193: vecinit(&x1_vec, c1_x, c1_y)
vecinit((&__pyx_v_x1_vec), __pyx_v_c1_x, __pyx_v_c1_y);
+194: vecinit(&x2_vec, c2_x, c2_y)
vecinit((&__pyx_v_x2_vec), __pyx_v_c2_x, __pyx_v_c2_y);
195:
+196: v = get_angle_free_vecR(vec1, vec2, obj1_mass, obj2_mass, x1_vec, x2_vec)
__pyx_v_v = __pyx_f_16ElasticCollision_7ec_real_get_angle_free_vecR(__pyx_v_vec1, __pyx_v_vec2, __pyx_v_obj1_mass, __pyx_v_obj2_mass, __pyx_v_x1_vec, __pyx_v_x2_vec); }
197:
+198: return Vector2(v.vector1.x, v.vector1.y), \
__Pyx_XDECREF(__pyx_r); __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_Vector2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 198, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __pyx_t_7 = PyFloat_FromDouble(__pyx_v_v.vector1.x); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __pyx_t_8 = PyFloat_FromDouble(__pyx_v_v.vector1.y); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 198, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); __pyx_t_9 = NULL; __pyx_t_10 = 0; if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) { __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_6); if (likely(__pyx_t_9)) { PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); __Pyx_INCREF(__pyx_t_9); __Pyx_INCREF(function); __Pyx_DECREF_SET(__pyx_t_6, function); __pyx_t_10 = 1; } } #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_7, __pyx_t_8}; __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 198, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; } else #endif #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_7, __pyx_t_8}; __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 198, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; } else #endif { __pyx_t_11 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 198, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_11); if (__pyx_t_9) { __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_9); __pyx_t_9 = NULL; } __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_11, 0+__pyx_t_10, __pyx_t_7); __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_11, 1+__pyx_t_10, __pyx_t_8); __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 198, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; } __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; /* … */ __pyx_t_11 = PyTuple_New(2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 198, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_11); __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_1); __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_11, 1, __pyx_t_6); __pyx_t_1 = 0; __pyx_t_6 = 0; __pyx_r = ((PyObject*)__pyx_t_11); __pyx_t_11 = 0; goto __pyx_L0;
+199: Vector2(v.vector2.x, v.vector2.y)
/* "ElasticCollision/real/ec_real.pyx":199 * * return Vector2(v.vector1.x, v.vector1.y), \ * Vector2(v.vector2.x, v.vector2.y) # <<<<<<<<<<<<<< * * # ***************************END INTERFACE ************************************* */ __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_Vector2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 199, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_11); __pyx_t_8 = PyFloat_FromDouble(__pyx_v_v.vector2.x); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 199, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_8); __pyx_t_7 = PyFloat_FromDouble(__pyx_v_v.vector2.y); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 199, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_7); __pyx_t_9 = NULL; __pyx_t_10 = 0; if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_11))) { __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_11); if (likely(__pyx_t_9)) { PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_11); __Pyx_INCREF(__pyx_t_9); __Pyx_INCREF(function); __Pyx_DECREF_SET(__pyx_t_11, function); __pyx_t_10 = 1; } } #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_11)) { PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_8, __pyx_t_7}; __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_11, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 199, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; } else #endif #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_11)) { PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_8, __pyx_t_7}; __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_11, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 199, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; } else #endif { __pyx_t_12 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 199, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_12); if (__pyx_t_9) { __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_9); __pyx_t_9 = NULL; } __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_12, 0+__pyx_t_10, __pyx_t_8); __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_12, 1+__pyx_t_10, __pyx_t_7); __pyx_t_8 = 0; __pyx_t_7 = 0; __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_11, __pyx_t_12, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 199, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; } __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
200:
201: # ***************************END INTERFACE *************************************
202:
203:
204:
205: # *************************** CYTHON INTERFACE *********************************
206:
207: @cython.boundscheck(False)
208: @cython.wraparound(False)
209: @cython.nonecheck(False)
210: @cython.cdivision(True)
+211: cdef v_struct get_momentum_trigonometry_vecR(
static struct v_struct __pyx_f_16ElasticCollision_7ec_real_get_momentum_trigonometry_vecR(float __pyx_v_obj1_cx, float __pyx_v_obj1_cy, float __pyx_v_obj2_cx, float __pyx_v_obj2_cy, struct vector2d __pyx_v_obj1_vec, struct vector2d __pyx_v_obj2_vec, float __pyx_v_obj1_mass, float __pyx_v_obj2_mass) { float __pyx_v_phi; float __pyx_v_theta1; float __pyx_v_theta2; float __pyx_v_v1_length; float __pyx_v_v2_length; struct vector2d __pyx_v_v1; struct vector2d __pyx_v_v2; struct v_struct __pyx_v_collision; struct v_struct __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
212: float obj1_cx, float obj1_cy,
213: float obj2_cx, float obj2_cy,
214: vector2d obj1_vec, vector2d obj2_vec,
215: float obj1_mass, float obj2_mass
216: )nogil:
217: """
218: RETURN VECTORS V1 & V2 OF ORIGINAL OBJECTS AFTER
219: COLLISION (TRIGONOMETRY)
220:
221: :param obj1_cx : float; Object 1 centre x coordinate
222: :param obj1_cy : float; object 1 centre y coordinate
223: :param obj2_cx : float; object 2 centre x coordinate
224: :param obj2_cy : float; object 2 centre y coordinate
225: :param obj1_vec : float; object 1 vector velocity/trajectory
226: :param obj2_vec : float; object 2 vector velocity/trajectory
227: :param obj1_mass: float; object 1 mass in kilogrammes
228: :param obj2_mass: float; object 2 mass in kilogrammes
229: :return: return a cython object v_struct (tuple of vector2d v1, v2)
230: """
231:
232: cdef:
+233: float phi = get_contact_angle(obj1_cx, obj1_cy, obj2_cx, obj2_cy)
__pyx_v_phi = __pyx_f_16ElasticCollision_7ec_real_get_contact_angle(__pyx_v_obj1_cx, __pyx_v_obj1_cy, __pyx_v_obj2_cx, __pyx_v_obj2_cy);
+234: float theta1 = get_theta_angle(obj1_vec)
__pyx_v_theta1 = __pyx_f_16ElasticCollision_7ec_real_get_theta_angle(__pyx_v_obj1_vec);
+235: float theta2 = get_theta_angle(obj2_vec)
__pyx_v_theta2 = __pyx_f_16ElasticCollision_7ec_real_get_theta_angle(__pyx_v_obj2_vec);
236: float v1_length, v2_length
237: vector2d v1
238: vector2d v2
239: v_struct collision
240:
+241: v1_length = vlength(&obj1_vec)
__pyx_v_v1_length = vlength((&__pyx_v_obj1_vec));
+242: v2_length = vlength(&obj2_vec)
__pyx_v_v2_length = vlength((&__pyx_v_obj2_vec));
243:
+244: v1 = get_v1R(v1_length, v2_length, theta1, theta2, phi, obj1_mass, obj2_mass)
__pyx_v_v1 = __pyx_f_16ElasticCollision_7ec_real_get_v1R(__pyx_v_v1_length, __pyx_v_v2_length, __pyx_v_theta1, __pyx_v_theta2, __pyx_v_phi, __pyx_v_obj1_mass, __pyx_v_obj2_mass);
+245: v2 = get_v2R(v1_length, v2_length, theta1, theta2, phi, obj1_mass, obj2_mass)
__pyx_v_v2 = __pyx_f_16ElasticCollision_7ec_real_get_v2R(__pyx_v_v1_length, __pyx_v_v2_length, __pyx_v_theta1, __pyx_v_theta2, __pyx_v_phi, __pyx_v_obj1_mass, __pyx_v_obj2_mass);
246:
+247: collision.vector1 = v1
__pyx_v_collision.vector1 = __pyx_v_v1;
+248: collision.vector2 = v2
__pyx_v_collision.vector2 = __pyx_v_v2;
249:
+250: return collision
__pyx_r = __pyx_v_collision; goto __pyx_L0;
251:
252:
+253: cdef vector2d get_v1R(
static struct vector2d __pyx_f_16ElasticCollision_7ec_real_get_v1R(float __pyx_v_v1_, float __pyx_v_v2_, float __pyx_v_theta1_, float __pyx_v_theta2_, float __pyx_v_phi_, float __pyx_v_m1_, float __pyx_v_m2_) { float __pyx_v_numerator; float __pyx_v_v1x; float __pyx_v_v1y; float __pyx_v_r1; float __pyx_v_r2; float __pyx_v_m12; struct vector2d __pyx_v_v1_vec; struct vector2d __pyx_r; #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save; #endif __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("get_v1R", 1); /* … */ /* function exit code */ __Pyx_pretend_to_initialize(&__pyx_r); goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); __Pyx_WriteUnraisable("ElasticCollision.ec_real.get_v1R", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1); __Pyx_pretend_to_initialize(&__pyx_r); __pyx_L0:; #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif return __pyx_r; }
254: float v1_, float v2_,
255: float theta1_, float theta2_,
256: float phi_,
257: float m1_, float m2_
258: )nogil:
+259: """
/*try:*/ { /* … */ /*finally:*/ { __pyx_L3_return: { #ifdef WITH_THREAD __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif goto __pyx_L0; } __pyx_L4_error: { #ifdef WITH_THREAD __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif goto __pyx_L1_error; } }
260: RETURN SCALAR SIZE V1 OF THE ORIGINAL OBJECT
261: REPRESENTED BY (V1, THETA1, M1) TRIGONOMETRY
262:
263: Where v1_ and v2_ are the scalar sizes of the two original speeds of the objects, m1_ and m2_
264: are their masses, θ1 and θ2 are their movement angles, that is,v1x = v1_.cos(θ1) , v1y = v1_.sin(θ1)
265: (meaning moving directly down to the right is either a -45° angle, or a 315°angle), and lowercase phi_ (φ)
266: is the contact angle.
267:
268: :param v1_ : float; object1 vector_ length
269: :param v2_ : float; object2 vector_ length
270: :param theta1_ : float; Θ1 angle in radians (object1)
271: :param theta2_ : float; Θ2 angle in radians (object2)
272: :param phi_ : float; φ contact angle in radians
273: :param m1_ : float; Mass in kilograms, must be > 0 (object1)
274: :param m2_ : float; Mass in kilograms, must be > 0(object2)
275: :return : Returns a vector2d cython object, vector v1
276: :rtype : vector2d
277: """
278: cdef:
279: float numerator, v1x, v1y
280: float r1, r2
+281: float m12 = m1_ + m2_
__pyx_v_m12 = (__pyx_v_m1_ + __pyx_v_m2_);
282: vector2d v1_vec
283:
+284: if v1_ <=0.0 or v2_ <=0.0:
__pyx_t_2 = ((__pyx_v_v1_ <= 0.0) != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } __pyx_t_2 = ((__pyx_v_v2_ <= 0.0) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; if (__pyx_t_1) { /* … */ }
+285: with gil:
{ #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif /*try:*/ { /* … */ /*finally:*/ { __pyx_L10_error: { #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif goto __pyx_L4_error; } } }
+286: raise ValueError(
__pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 286, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_Raise(__pyx_t_5, 0, 0, 0); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __PYX_ERR(0, 286, __pyx_L10_error) }
287: '\n|v1_|, |v2_| magnitude must be >= 0.0'
+288: '\n|v1|=%s |v2|=%s ' % (v1_, v2_))
__pyx_t_3 = PyFloat_FromDouble(__pyx_v_v1_); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 288, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyFloat_FromDouble(__pyx_v_v2_); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 288, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 288, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4); __pyx_t_3 = 0; __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_v1__v2__magnitude_must_be_0_0_v, __pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 288, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+289: if m12 <= 0.0:
__pyx_t_1 = ((__pyx_v_m12 <= 0.0) != 0); if (__pyx_t_1) { /* … */ }
+290: with gil:
{ #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif /*try:*/ { /* … */ /*finally:*/ { __pyx_L14_error: { #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif goto __pyx_L4_error; } } }
+291: raise ValueError("Object's mass should be > 0.0")
__pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 291, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_Raise(__pyx_t_5, 0, 0, 0); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __PYX_ERR(0, 291, __pyx_L14_error) } /* … */ __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_Object_s_mass_should_be_0_0); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 291, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_);
292:
+293: r1 = theta1_ - phi_
__pyx_v_r1 = (__pyx_v_theta1_ - __pyx_v_phi_);
+294: r2 = phi_ + <float>M_PI2
__pyx_v_r2 = (__pyx_v_phi_ + ((float)1.5707963267948966));
+295: numerator = v1_ * <float>cos(r1) * (m1_ - m2_) + <float>(2 * m2_) * v2_ * <float>cos(theta2_ - phi_)
__pyx_v_numerator = (((__pyx_v_v1_ * ((float)cos(__pyx_v_r1))) * (__pyx_v_m1_ - __pyx_v_m2_)) + ((((float)(2.0 * __pyx_v_m2_)) * __pyx_v_v2_) * ((float)cos((__pyx_v_theta2_ - __pyx_v_phi_)))));
+296: v1x = numerator * <float>cos(phi_) / m12 + v1_ * <float>sin(r1) * <float>cos(r2)
__pyx_v_v1x = (((__pyx_v_numerator * ((float)cos(__pyx_v_phi_))) / __pyx_v_m12) + ((__pyx_v_v1_ * ((float)sin(__pyx_v_r1))) * ((float)cos(__pyx_v_r2))));
+297: v1y = numerator * <float>sin(phi_) / m12 + v1_ * <float>sin(r1) * <float>sin(r2)
__pyx_v_v1y = (((__pyx_v_numerator * ((float)sin(__pyx_v_phi_))) / __pyx_v_m12) + ((__pyx_v_v1_ * ((float)sin(__pyx_v_r1))) * ((float)sin(__pyx_v_r2))));
298:
+299: vecinit(&v1_vec, v1x, v1y)
vecinit((&__pyx_v_v1_vec), __pyx_v_v1x, __pyx_v_v1y);
+300: return v1_vec
__pyx_r = __pyx_v_v1_vec; goto __pyx_L3_return; }
301:
302:
303: @cython.boundscheck(False)
304: @cython.wraparound(False)
305: @cython.nonecheck(False)
306: @cython.cdivision(True)
+307: cdef vector2d get_v2R(
static struct vector2d __pyx_f_16ElasticCollision_7ec_real_get_v2R(float __pyx_v_v1_, float __pyx_v_v2_, float __pyx_v_theta1_, float __pyx_v_theta2_, float __pyx_v_phi_, float __pyx_v_m1_, float __pyx_v_m2_) { float __pyx_v_numerator; float __pyx_v_v2x; float __pyx_v_v2y; float __pyx_v_r1; float __pyx_v_r2; float __pyx_v_m21; struct vector2d __pyx_v_v2_vec; struct vector2d __pyx_r; #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save; #endif __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("get_v2R", 1); /* … */ /* function exit code */ __Pyx_pretend_to_initialize(&__pyx_r); goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); __Pyx_WriteUnraisable("ElasticCollision.ec_real.get_v2R", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1); __Pyx_pretend_to_initialize(&__pyx_r); __pyx_L0:; #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif return __pyx_r; }
308: float v1_, float v2_,
309: float theta1_, float theta2_,
310: float phi_,
311: float m1_, float m2_
312: )nogil:
+313: """
/*try:*/ { /* … */ /*finally:*/ { __pyx_L3_return: { #ifdef WITH_THREAD __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif goto __pyx_L0; } __pyx_L4_error: { #ifdef WITH_THREAD __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif goto __pyx_L1_error; } }
314: RETURN SCALAR SIZE V2_ OF THE ORIGINAL OBJECT
315: REPRESENTED BY (V2_, THETA2_, M2_) TRIGONOMETRY
316:
317: where v1_ and v2_ are the scalar sizes of the two original speeds of the objects, m1_ and m2_
318: are their masses, θ1 and θ2 are their movement angles, that is,v1x = v1_.cos(θ1) , v1y = v1_.sin(θ1)
319: (meaning moving directly down to the right is either a -45° angle, or a 315°angle), and lowercase phi_ (φ)
320: is the contact angle.
321:
322: :param v1_ : float; object1 vector_ length
323: :param v2_ : float; object2 vector_ length
324: :param theta1_: float; Θ1 angle in radians (object1)
325: :param theta2_: float; Θ2 angle in radians (object2)
326: :param phi_ : float; φ contact angle in radians
327: :param m1_ : float; Mass in kilograms, must be > 0 (object1)
328: :param m2_ : float; Mass in kilograms, must be > 0(object2)
329: :return : float; Returns a direction vector_
330: :return : float; Return a cython object, vector v2
331: """
332: cdef:
333: float numerator, v2x, v2y
334: float r1, r2
+335: float m21 = m2_ + m1_
__pyx_v_m21 = (__pyx_v_m2_ + __pyx_v_m1_);
336: vector2d v2_vec
337:
+338: r1 = (theta2_ - phi_)
__pyx_v_r1 = (__pyx_v_theta2_ - __pyx_v_phi_);
+339: r2 = phi_ + <float>M_PI2
__pyx_v_r2 = (__pyx_v_phi_ + ((float)1.5707963267948966));
340:
+341: if v1_ <=0.0 or v2_ <=0.0:
__pyx_t_2 = ((__pyx_v_v1_ <= 0.0) != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } __pyx_t_2 = ((__pyx_v_v2_ <= 0.0) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; if (__pyx_t_1) { /* … */ }
+342: with gil:
{ #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif /*try:*/ { /* … */ /*finally:*/ { __pyx_L10_error: { #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif goto __pyx_L4_error; } } }
+343: raise ValueError(
__pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 343, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_Raise(__pyx_t_5, 0, 0, 0); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __PYX_ERR(0, 343, __pyx_L10_error) }
344: "\n|v1_|, |v2_| magnitude must be >= 0.0\n"
+345: "|v1|=%s |v2|=%s " % (v1_, v2_))
__pyx_t_3 = PyFloat_FromDouble(__pyx_v_v1_); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 345, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyFloat_FromDouble(__pyx_v_v2_); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 345, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 345, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4); __pyx_t_3 = 0; __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_v1__v2__magnitude_must_be_0_0_v, __pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 345, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+346: if m21 <= 0.0:
__pyx_t_1 = ((__pyx_v_m21 <= 0.0) != 0); if (__pyx_t_1) { /* … */ }
+347: with gil:
{ #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif /*try:*/ { /* … */ /*finally:*/ { __pyx_L14_error: { #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif goto __pyx_L4_error; } } }
+348: raise ValueError("Object's mass should be > 0.0")
__pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 348, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_Raise(__pyx_t_5, 0, 0, 0); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __PYX_ERR(0, 348, __pyx_L14_error) }
349:
+350: numerator = v2_ * <float>cos(r1) * <float>(m2_ - m1_) + <float>(2 * m1_) * v1_ * <float>cos(theta1_ - phi_)
__pyx_v_numerator = (((__pyx_v_v2_ * ((float)cos(__pyx_v_r1))) * ((float)(__pyx_v_m2_ - __pyx_v_m1_))) + ((((float)(2.0 * __pyx_v_m1_)) * __pyx_v_v1_) * ((float)cos((__pyx_v_theta1_ - __pyx_v_phi_)))));
+351: v2x = numerator * <float>cos(phi_) / m21 + v2_ * <float>sin(r1) * <float>cos(r2)
__pyx_v_v2x = (((__pyx_v_numerator * ((float)cos(__pyx_v_phi_))) / __pyx_v_m21) + ((__pyx_v_v2_ * ((float)sin(__pyx_v_r1))) * ((float)cos(__pyx_v_r2))));
+352: v2y = numerator * <float>sin(phi_) / m21 + v2_ * <float>sin(r1) * <float>sin(r2)
__pyx_v_v2y = (((__pyx_v_numerator * ((float)sin(__pyx_v_phi_))) / __pyx_v_m21) + ((__pyx_v_v2_ * ((float)sin(__pyx_v_r1))) * ((float)sin(__pyx_v_r2))));
353:
+354: vecinit(&v2_vec, v2x, v2y)
vecinit((&__pyx_v_v2_vec), __pyx_v_v2x, __pyx_v_v2y);
+355: return v2_vec
__pyx_r = __pyx_v_v2_vec; goto __pyx_L3_return; }
356:
357:
358:
359: # ****************************** ANGLE FREE METHOD *******************************************
360:
361: # ***************************************************************
362: # Angle free representation, the changed velocities are computed
363: # using centers x1 and x2 at the time of contact.
364: # ***************************************************************
365: @cython.boundscheck(False)
366: @cython.wraparound(False)
367: @cython.nonecheck(False)
368: @cython.cdivision(True)
+369: cdef vector2d get_v1_angle_free_vecR(
static struct vector2d __pyx_f_16ElasticCollision_7ec_real_get_v1_angle_free_vecR(struct vector2d __pyx_v_v1, struct vector2d __pyx_v_v2, float __pyx_v_m1, float __pyx_v_m2, struct vector2d __pyx_v_x1, struct vector2d __pyx_v_x2) { float __pyx_v_m12; float __pyx_v_mass; struct vector2d __pyx_v_v12; struct vector2d __pyx_v_x12; float __pyx_v_x12_length; float __pyx_v_d; struct vector2d __pyx_r; #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save; #endif __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("get_v1_angle_free_vecR", 1); /* … */ /* function exit code */ __Pyx_pretend_to_initialize(&__pyx_r); goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); __Pyx_WriteUnraisable("ElasticCollision.ec_real.get_v1_angle_free_vecR", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1); __Pyx_pretend_to_initialize(&__pyx_r); __pyx_L0:; #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif return __pyx_r; }
370: vector2d v1, vector2d v2,
371: float m1, float m2,
372: vector2d x1, vector2d x2
373: )nogil:
+374: """
/*try:*/ { /* … */ /*finally:*/ { __pyx_L3_return: { #ifdef WITH_THREAD __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif goto __pyx_L0; } __pyx_L4_error: { #ifdef WITH_THREAD __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif goto __pyx_L1_error; } }
375: SCALAR SIZE V1_ OF THE ORIGINAL OBJECT SPEED REPRESENTED
376: BY (V1_, M1_, X1 ARGUMENTS).
377:
378: :param v1: vector2d, object1 vector_
379: :param v2: vector2d, object2 vector_
380: :param m1: float; object1 mass_ in kilograms, must be > 0
381: :param m2: float; object2 mass_ in kilograms, must be > 0
382: :param x1: vector2d, object1 centre_
383: :param x2: vector2d, object2 centre_
384: :return: vector2d, resultant vector_ for object1
385: """
+386: cdef float m12 = m1 + m2
__pyx_v_m12 = (__pyx_v_m1 + __pyx_v_m2);
387:
+388: if vlength(&v1) <=0.0 or vlength(&v2) <= 0.0:
__pyx_t_2 = ((vlength((&__pyx_v_v1)) <= 0.0) != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } __pyx_t_2 = ((vlength((&__pyx_v_v2)) <= 0.0) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; if (__pyx_t_1) { /* … */ }
+389: with gil:
{ #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif /*try:*/ { /* … */ /*finally:*/ { __pyx_L10_error: { #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif goto __pyx_L4_error; } } }
+390: raise ValueError("\n|v1|, |v2| magnitude must be >= 0.0\n"
__pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 390, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_Raise(__pyx_t_5, 0, 0, 0); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __PYX_ERR(0, 390, __pyx_L10_error) }
+391: "|v1|=%s |v2|=%s " % (vlength(&v1), vlength(&v2)))
__pyx_t_3 = PyFloat_FromDouble(vlength((&__pyx_v_v1))); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 391, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyFloat_FromDouble(vlength((&__pyx_v_v2))); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 391, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 391, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4); __pyx_t_3 = 0; __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_v1_v2_magnitude_must_be_0_0_v1, __pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 391, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+392: if m12 <= 0.0:
__pyx_t_1 = ((__pyx_v_m12 <= 0.0) != 0); if (__pyx_t_1) { /* … */ }
+393: with gil:
{ #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif /*try:*/ { /* … */ /*finally:*/ { __pyx_L14_error: { #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif goto __pyx_L4_error; } } }
+394: raise ValueError("Object's mass should be > 0.0")
__pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 394, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_Raise(__pyx_t_5, 0, 0, 0); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __PYX_ERR(0, 394, __pyx_L14_error) }
395:
+396: cdef float mass = <float>(2.0 * m2) / m12 # mass coefficient in the equation
__pyx_v_mass = (((float)(2.0 * __pyx_v_m2)) / __pyx_v_m12);
397: cdef vector2d v12, x12 # 2d vector declaration v12 & x12
398:
+399: v12 = subcomponents(v1, v2) # subtract v1 and v2 (v1 - v2).
__pyx_v_v12 = subcomponents(__pyx_v_v1, __pyx_v_v2);
400: # subcomponents return a new vector v12,
401: # original vector v1 & v2 components remain unchanged.
+402: x12 = subcomponents(x1, x2) # Objects centre difference (x1 - x2).
__pyx_v_x12 = subcomponents(__pyx_v_x1, __pyx_v_x2);
403: # subcomponents return a new vector x12
404: # x1 & x2 vector components remain unchanged.
+405: cdef float x12_length = vlength(&x12) # x12 vector length (scalar)
__pyx_v_x12_length = vlength((&__pyx_v_x12));
+406: cdef float d = dot(&v12, &x12) # vector dot product v12 & x12, return a scalar value (float)
__pyx_v_d = dot((&__pyx_v_v12), (&__pyx_v_x12));
407: # rescale vector x12
+408: scale_inplace(<float>(mass * d) / <float>(x12_length * x12_length), &x12)
scale_inplace((((float)(__pyx_v_mass * __pyx_v_d)) / ((float)(__pyx_v_x12_length * __pyx_v_x12_length))), (&__pyx_v_x12));
+409: return subcomponents(v1, x12)
__pyx_r = subcomponents(__pyx_v_v1, __pyx_v_x12); goto __pyx_L3_return; }
410:
411:
412:
413: # ***************************************************************
414: # Angle free representation, the changed velocities are computed
415: # using centers x1 and x2 at the time of contact.
416: # ***************************************************************
417: @cython.boundscheck(False)
418: @cython.wraparound(False)
419: @cython.nonecheck(False)
420: @cython.cdivision(True)
+421: cdef vector2d get_v2_angle_free_vecR(
static struct vector2d __pyx_f_16ElasticCollision_7ec_real_get_v2_angle_free_vecR(struct vector2d __pyx_v_v1, struct vector2d __pyx_v_v2, float __pyx_v_m1, float __pyx_v_m2, struct vector2d __pyx_v_x1, struct vector2d __pyx_v_x2) { float __pyx_v_m12; float __pyx_v_mass; struct vector2d __pyx_v_v21; struct vector2d __pyx_v_x21; float __pyx_v_x21_length; float __pyx_v_d; struct vector2d __pyx_r; #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save; #endif __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("get_v2_angle_free_vecR", 1); /* … */ /* function exit code */ __Pyx_pretend_to_initialize(&__pyx_r); goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_5); __Pyx_WriteUnraisable("ElasticCollision.ec_real.get_v2_angle_free_vecR", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1); __Pyx_pretend_to_initialize(&__pyx_r); __pyx_L0:; #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif return __pyx_r; }
422: vector2d v1, vector2d v2,
423: float m1, float m2,
424: vector2d x1, vector2d x2
425: )nogil:
+426: """
/*try:*/ { /* … */ /*finally:*/ { __pyx_L3_return: { #ifdef WITH_THREAD __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif goto __pyx_L0; } __pyx_L4_error: { #ifdef WITH_THREAD __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif goto __pyx_L1_error; } }
427: SCALAR SIZE V2_ OF THE ORIGINAL OBJECT SPEED REPRESENTED
428: BY (V2_, M2_, X2 ARGUMENTS).
429:
430: :param v1: vector2d, object1 vector_
431: :param v2: vector2d, object2 vector_
432: :param m1: float; object1 mass_ in kilograms, must be > 0
433: :param m2: float; object2 mass_ in kilograms, must be > 0
434: :param x1: vector2d, object1 centre_
435: :param x2: vector2d, object2 centre_
436: :return: pygame.math.Vector2, resultant vector_ for object1
437: """
+438: cdef float m12 = (m1 + m2)
__pyx_v_m12 = (__pyx_v_m1 + __pyx_v_m2);
439:
440: # AT LEAST ONE OBJECT MUST BE IN MOTION
+441: if vlength(&v1) <=0.0 or vlength(&v2) <= 0.0:
__pyx_t_2 = ((vlength((&__pyx_v_v1)) <= 0.0) != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } __pyx_t_2 = ((vlength((&__pyx_v_v2)) <= 0.0) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; if (__pyx_t_1) { /* … */ }
+442: with gil:
{ #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif /*try:*/ { /* … */ /*finally:*/ { __pyx_L10_error: { #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif goto __pyx_L4_error; } } }
+443: raise ValueError("\n|v1|, |v2| magnitude must be >= 0.0"
__pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 443, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __Pyx_Raise(__pyx_t_5, 0, 0, 0); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __PYX_ERR(0, 443, __pyx_L10_error) }
+444: "\n|v1|=%s |v2|=%s " % (vlength(&v1), vlength(&v2)))
__pyx_t_3 = PyFloat_FromDouble(vlength((&__pyx_v_v1))); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 444, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = PyFloat_FromDouble(vlength((&__pyx_v_v2))); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 444, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 444, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4); __pyx_t_3 = 0; __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_v1_v2_magnitude_must_be_0_0_v1, __pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 444, __pyx_L10_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+445: if m12 <= 0.0:
__pyx_t_1 = ((__pyx_v_m12 <= 0.0) != 0); if (__pyx_t_1) { /* … */ }
+446: with gil:
{ #ifdef WITH_THREAD PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); #endif /*try:*/ { /* … */ /*finally:*/ { __pyx_L14_error: { #ifdef WITH_THREAD __Pyx_PyGILState_Release(__pyx_gilstate_save); #endif goto __pyx_L4_error; } } }
+447: raise ValueError("Object's mass should be > 0.0")
__pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 447, __pyx_L14_error) __Pyx_GOTREF(__pyx_t_5); __Pyx_Raise(__pyx_t_5, 0, 0, 0); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; __PYX_ERR(0, 447, __pyx_L14_error) }
448:
+449: cdef float mass = <float>(2.0 * m1) / m12 # mass coefficient in the equation
__pyx_v_mass = (((float)(2.0 * __pyx_v_m1)) / __pyx_v_m12);
450: cdef vector2d v21, x21 # 2d vector declaration v21 & x21
451:
+452: v21 = subcomponents(v2, v1) # subtract v2 and v1 (v2 - v1).
__pyx_v_v21 = subcomponents(__pyx_v_v2, __pyx_v_v1);
453: # subcomponents return a new vector v21,
454: # original vector v2 & v1 components remain unchanged.
+455: x21 = subcomponents(x2, x1) # Objects centre difference (x2 - x1).
__pyx_v_x21 = subcomponents(__pyx_v_x2, __pyx_v_x1);
456: # subcomponents return a new vector x21
457: # x2 & x1 vector components remain unchanged.
+458: cdef float x21_length = vlength(&x21) # x21 vector length (scalar)
__pyx_v_x21_length = vlength((&__pyx_v_x21));
+459: cdef float d = dot(&v21, &x21) # vector dot product v21 & x21, return a scalar value (float)
__pyx_v_d = dot((&__pyx_v_v21), (&__pyx_v_x21));
460: # rescale vector x21
+461: scale_inplace(<float>(mass * d) / <float>(x21_length * x21_length), &x21)
scale_inplace((((float)(__pyx_v_mass * __pyx_v_d)) / ((float)(__pyx_v_x21_length * __pyx_v_x21_length))), (&__pyx_v_x21));
+462: return subcomponents(v2, x21)
__pyx_r = subcomponents(__pyx_v_v2, __pyx_v_x21); goto __pyx_L3_return; }
463:
464:
465: # ************************************************************************
466: # Angle free calculation, return V1 and V2
467: # ************************************************************************
468: @cython.boundscheck(False)
469: @cython.wraparound(False)
470: @cython.nonecheck(False)
471: @cython.cdivision(True)
+472: cdef v_struct get_angle_free_vecR(
static struct v_struct __pyx_f_16ElasticCollision_7ec_real_get_angle_free_vecR(struct vector2d __pyx_v_v1, struct vector2d __pyx_v_v2, float __pyx_v_m1, float __pyx_v_m2, struct vector2d __pyx_v_x1, struct vector2d __pyx_v_x2) { struct vector2d __pyx_v_v11; struct vector2d __pyx_v_v22; struct v_struct __pyx_v_collision; struct v_struct __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
473: vector2d v1, vector2d v2,
474: float m1, float m2,
475: vector2d x1, vector2d x2
476: )nogil:
477: """
478: RETURN BOTH FINAL VELOCITIES VECTORS V1 & V2
479:
480: :param v1: vector2d, object1 vector_
481: :param v2: vector2d, object2 vector_
482: :param m1: float; object1 mass_ in kilograms, must be > 0
483: :param m2: float; object2 mass_ in kilograms, must be > 0
484: :param x1: vector2d, object1 centre_
485: :param x2: vector2d, object2 centre_
486: :return: tuple, (object1 resultant vector_, object2 resultant vector_)
487: """
488: cdef vector2d v11, v22
+489: v11 = get_v1_angle_free_vecR(v1, v2, m1, m2, x1, x2)
__pyx_v_v11 = __pyx_f_16ElasticCollision_7ec_real_get_v1_angle_free_vecR(__pyx_v_v1, __pyx_v_v2, __pyx_v_m1, __pyx_v_m2, __pyx_v_x1, __pyx_v_x2);
+490: v22 = get_v2_angle_free_vecR(v1, v2, m1, m2, x1, x2)
__pyx_v_v22 = __pyx_f_16ElasticCollision_7ec_real_get_v2_angle_free_vecR(__pyx_v_v1, __pyx_v_v2, __pyx_v_m1, __pyx_v_m2, __pyx_v_x1, __pyx_v_x2);
491: cdef v_struct collision
+492: collision.vector1 = v11
__pyx_v_collision.vector1 = __pyx_v_v11;
+493: collision.vector2 = v22
__pyx_v_collision.vector2 = __pyx_v_v22;
+494: return collision
__pyx_r = __pyx_v_collision; goto __pyx_L0;
495:
496:
497: # # ***************************************************************************************************
498:
499: @cython.boundscheck(False)
500: @cython.wraparound(False)
501: @cython.nonecheck(False)
502: @cython.cdivision(True)
+503: cdef float vector_length(float x, float y)nogil:
static float __pyx_f_16ElasticCollision_7ec_real_vector_length(float __pyx_v_x, float __pyx_v_y) { float __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
504: """
505: CALCULATE A VECTOR LENGTH GIVEN ITS COMPONENTS (SCALAR VALUES)
506:
507: :param x: float; x coordinate
508: :param y: float; y coordinate
509: :return: float; vector length
510: """
+511: return <float>sqrt(x * x + y * y)
__pyx_r = ((float)sqrt(((__pyx_v_x * __pyx_v_x) + (__pyx_v_y * __pyx_v_y)))); goto __pyx_L0;
512:
513: @cython.boundscheck(False)
514: @cython.wraparound(False)
515: @cython.nonecheck(False)
516: @cython.cdivision(True)
+517: cdef float get_contact_angle(
static float __pyx_f_16ElasticCollision_7ec_real_get_contact_angle(float __pyx_v_v1x, float __pyx_v_v1y, float __pyx_v_v2x, float __pyx_v_v2y) { float __pyx_v_dx; float __pyx_v_dy; float __pyx_v_phi; float __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
518: float v1x, float v1y,
519: float v2x, float v2y
520: )nogil:
521: """
522: RETURN THE CONTACT ANGLE Φ [0, -2Π] IN RADIANS BETWEEN OBJ1 AND
523: OBJ2 OR [0 ... -360 degrees].
524:
525: The distance dx & dy between both objects is determine by
526: dx = v2x - v1x & dy = v2y - v1y.
527:
528: * Angle φ between the two objects at the point of collision
529: This function returns the angle φ at the time of the contact.
530:
531: * atan2(y, x) returns value of atan(y/x) in radians. The atan2() method returns
532: a numeric value between –pi and pi representing the angle theta of a (x, y)
533: point and positive x-axis.
534:
535: :param v1x : object 1 centre value (x component) at time of contact.
536: :param v1y : object 1 centre value (y component) at time of contact.
537: :param v2x : object 2 centre value (x component) at time of contact.
538: :param v2y : object 2 centre value (y component) at time of contact.
539: :return : float; contact angle in radians [0, -2π]
540: :rtype : float (angle φ radians)
541: """
542: cdef:
543: float dx, dy
544: float phi
545:
+546: dx = v2x - v1x
__pyx_v_dx = (__pyx_v_v2x - __pyx_v_v1x);
+547: dy = v2y - v1y
__pyx_v_dy = (__pyx_v_v2y - __pyx_v_v1y);
548:
+549: phi = <float> atan2(dy, dx)
__pyx_v_phi = ((float)atan2(__pyx_v_dy, __pyx_v_dx));
+550: if phi > 0.0:
__pyx_t_1 = ((__pyx_v_phi > 0.0) != 0); if (__pyx_t_1) { /* … */ }
+551: phi -= <float>(2.0 * M_PI)
__pyx_v_phi = (__pyx_v_phi - ((float)(2.0 * 3.141592653589793)));
552: # phi *= -1.0
+553: return <float> phi
__pyx_r = ((float)__pyx_v_phi); goto __pyx_L0;
554:
555: @cython.boundscheck(False)
556: @cython.wraparound(False)
557: @cython.nonecheck(False)
558: @cython.cdivision(True)
+559: cdef float get_theta_angle(vector2d vector_)nogil:
static float __pyx_f_16ElasticCollision_7ec_real_get_theta_angle(struct vector2d __pyx_v_vector_) { float __pyx_v_theta; float __pyx_v_vl; float __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
560: """
561: RETURN THETA ANGLE Θ IN RADIANS [Π, -Π]
562:
563: Angle theta at point of collision.
564:
565: * vector_ correspond to the initial angle for an object, similar
566: to the object direction at time of contact. The vector must be normalized range [-1.0 ... 1.0]
567: vector_ contains the vector components (x, y) describing the object velocity and direction
568: (angle) at time of contact.
569: when the vector component (vector_.y) is > 0, the acos value is in range [0 ... pi]
570: When the vector component (vector_.y) is < 0, the acos value is multiply by -1 to
571: get an angle in range [0 ... -pi]
572:
573: * acos (angle domain) is be definition in range y [0 ... +pi] and x values [-1 ... +1]
574: y [0 ... 180] degrees
575:
576: :param vector_: vector2d
577: :return : float (angle Θ in radians)
578: """
579: cdef:
580: float theta
+581: float vl = vlength(&vector_)
__pyx_v_vl = vlength((&__pyx_v_vector_));
582:
+583: if vl != <float>0.0:
__pyx_t_1 = ((__pyx_v_vl != ((float)0.0)) != 0); if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+584: theta = <float> acos(vector_.x / vl)
__pyx_v_theta = ((float)acos((__pyx_v_vector_.x / __pyx_v_vl)));
585: else:
586: # AT CONTACT TIME, OBJECT SHOULD BE MOVING.
587: # IDEALLY PROGRAM SHOULD RAISE AN ERROR MSG.
+588: return <float>0.0
/*else*/ { __pyx_r = ((float)0.0); goto __pyx_L0; } __pyx_L3:;
+589: if vector_.y < 0.0:
__pyx_t_1 = ((__pyx_v_vector_.y < 0.0) != 0); if (__pyx_t_1) { /* … */ }
+590: theta *= -<float>1.0
__pyx_v_theta = (__pyx_v_theta * (-((float)1.0)));
591:
+592: theta = <float> min(theta, M_PI)
__pyx_t_2 = 3.141592653589793; __pyx_t_3 = __pyx_v_theta; if (((__pyx_t_2 < __pyx_t_3) != 0)) { __pyx_t_4 = __pyx_t_2; } else { __pyx_t_4 = __pyx_t_3; } __pyx_v_theta = ((float)__pyx_t_4);
+593: theta = <float> max(theta, -M_PI)
__pyx_t_4 = -3.141592653589793; __pyx_t_3 = __pyx_v_theta; if (((__pyx_t_4 > __pyx_t_3) != 0)) { __pyx_t_2 = __pyx_t_4; } else { __pyx_t_2 = __pyx_t_3; } __pyx_v_theta = ((float)__pyx_t_2);
+594: return <float> theta
__pyx_r = ((float)__pyx_v_theta); goto __pyx_L0;