@@ -392,80 +392,95 @@ Py::Object Triangulation::calculate_plane_coefficients(const Py::Tuple &args)
392392 throw Py::ValueError (
393393 " z array must have same length as triangulation x and y arrays" );
394394 }
395- const double * zs = (const double *)PyArray_DATA (z);
396-
397- npy_intp dims[2 ] = {_ntri, 3 };
398- PyArrayObject* planes_array = (PyArrayObject*)PyArray_SimpleNew (
399- 2 , dims, PyArray_DOUBLE);
400- double * planes = (double *)PyArray_DATA (planes_array);
401- const int * tris = get_triangles_ptr ();
402- const double * xs = (const double *)PyArray_DATA (_x);
403- const double * ys = (const double *)PyArray_DATA (_y);
404- for (int tri = 0 ; tri < _ntri; ++tri)
395+
396+ PyArrayObject* planes_array = 0 ; // Array to return.
397+
398+ try
405399 {
406- if (is_masked (tri))
407- {
408- *planes++ = 0.0 ;
409- *planes++ = 0.0 ;
410- *planes++ = 0.0 ;
411- tris += 3 ;
412- }
413- else
400+ const double * zs = (const double *)PyArray_DATA (z);
401+
402+ npy_intp dims[2 ] = {_ntri, 3 };
403+ planes_array = (PyArrayObject*)PyArray_SimpleNew (2 , dims,
404+ PyArray_DOUBLE);
405+ double * planes = (double *)PyArray_DATA (planes_array);
406+ const int * tris = get_triangles_ptr ();
407+ const double * xs = (const double *)PyArray_DATA (_x);
408+ const double * ys = (const double *)PyArray_DATA (_y);
409+ for (int tri = 0 ; tri < _ntri; ++tri)
414410 {
415- // Equation of plane for all points r on plane is r.normal = p
416- // where normal is vector normal to the plane, and p is a constant.
417- // Rewrite as r_x*normal_x + r_y*normal_y + r_z*normal_z = p
418- // and rearrange to give
419- // r_z = (-normal_x/normal_z)*r_x + (-normal_y/normal_z)*r_y +
420- // p/normal_z
421- XYZ point0 (xs[*tris], ys[*tris], zs[*tris]);
422- tris++;
423- XYZ point1 (xs[*tris], ys[*tris], zs[*tris]);
424- tris++;
425- XYZ point2 (xs[*tris], ys[*tris], zs[*tris]);
426- tris++;
427-
428- XYZ normal = (point1 - point0).cross (point2 - point0);
429-
430- if (normal.z == 0.0 )
411+ if (is_masked (tri))
431412 {
432- // Normal is in x-y plane which means triangle consists of
433- // colinear points. Try to do the best we can by taking plane
434- // through longest side of triangle.
435- double length_sqr_01 = (point1 - point0).length_squared ();
436- double length_sqr_12 = (point2 - point1).length_squared ();
437- double length_sqr_20 = (point0 - point2).length_squared ();
438- if (length_sqr_01 > length_sqr_12)
439- {
440- if (length_sqr_01 > length_sqr_20)
441- normal = normal.cross (point1 - point0);
442- else
443- normal = normal.cross (point0 - point2);
444- }
445- else
446- {
447- if (length_sqr_12 > length_sqr_20)
448- normal = normal.cross (point2 - point1);
449- else
450- normal = normal.cross (point0 - point2);
451- }
413+ *planes++ = 0.0 ;
414+ *planes++ = 0.0 ;
415+ *planes++ = 0.0 ;
416+ tris += 3 ;
417+ }
418+ else
419+ {
420+ // Equation of plane for all points r on plane is r.normal = p
421+ // where normal is vector normal to the plane, and p is a
422+ // constant. Rewrite as
423+ // r_x*normal_x + r_y*normal_y + r_z*normal_z = p
424+ // and rearrange to give
425+ // r_z = (-normal_x/normal_z)*r_x + (-normal_y/normal_z)*r_y +
426+ // p/normal_z
427+ XYZ point0 (xs[*tris], ys[*tris], zs[*tris]);
428+ tris++;
429+ XYZ point1 (xs[*tris], ys[*tris], zs[*tris]);
430+ tris++;
431+ XYZ point2 (xs[*tris], ys[*tris], zs[*tris]);
432+ tris++;
433+
434+ XYZ normal = (point1 - point0).cross (point2 - point0);
452435
453436 if (normal.z == 0.0 )
454437 {
455- // The 3 triangle points have identical x and y! The best
456- // we can do here is take normal = (0,0,1) and for the
457- // constant p take the mean of the 3 points' z-values.
458- normal = XYZ (0.0 , 0.0 , 1.0 );
459- point0.z = (point0.z + point1.z + point2.z ) / 3.0 ;
438+ // Normal is in x-y plane which means triangle consists of
439+ // colinear points. Try to do the best we can by taking
440+ // plane through longest side of triangle.
441+ double length_sqr_01 = (point1 - point0).length_squared ();
442+ double length_sqr_12 = (point2 - point1).length_squared ();
443+ double length_sqr_20 = (point0 - point2).length_squared ();
444+ if (length_sqr_01 > length_sqr_12)
445+ {
446+ if (length_sqr_01 > length_sqr_20)
447+ normal = normal.cross (point1 - point0);
448+ else
449+ normal = normal.cross (point0 - point2);
450+ }
451+ else
452+ {
453+ if (length_sqr_12 > length_sqr_20)
454+ normal = normal.cross (point2 - point1);
455+ else
456+ normal = normal.cross (point0 - point2);
457+ }
458+
459+ if (normal.z == 0.0 )
460+ {
461+ // The 3 triangle points have identical x and y! The
462+ // best we can do here is take normal = (0,0,1) and for
463+ // the constant p take the mean of the 3 points'
464+ // z-values.
465+ normal = XYZ (0.0 , 0.0 , 1.0 );
466+ point0.z = (point0.z + point1.z + point2.z ) / 3.0 ;
467+ }
460468 }
461- }
462469
463- *planes++ = -normal.x / normal.z ; // x
464- *planes++ = -normal.y / normal.z ; // y
465- *planes++ = normal.dot (point0) / normal.z ; // constant
470+ *planes++ = -normal.x / normal.z ; // x
471+ *planes++ = -normal.y / normal.z ; // y
472+ *planes++ = normal.dot (point0) / normal.z ; // constant
473+ }
466474 }
467475 }
476+ catch (...)
477+ {
478+ Py_DECREF (z);
479+ Py_XDECREF (planes_array);
480+ throw ;
481+ }
468482
483+ Py_DECREF (z);
469484 return Py::asObject ((PyObject*)planes_array);
470485}
471486
0 commit comments