@@ -381,24 +381,40 @@ QuadContourGenerator::~QuadContourGenerator()
381381 delete [] _cache;
382382}
383383
384- void QuadContourGenerator::append_contour_line_to_vertices (
384+ void QuadContourGenerator::append_contour_line_to_vertices_and_codes (
385385 ContourLine& contour_line,
386- PyObject* vertices_list) const
386+ PyObject* vertices_list,
387+ PyObject* codes_list) const
387388{
388389 assert (vertices_list != 0 && " Null python vertices_list" );
390+ assert (codes_list != 0 && " Null python codes_list" );
389391
390392 // Convert ContourLine to python equivalent, and clear it.
391- npy_intp dims[2 ] = {static_cast <npy_intp>(contour_line.size ()), 2 };
392- numpy::array_view<double , 2 > line (dims);
393- npy_intp i = 0 ;
393+ npy_intp npoints = static_cast <npy_intp>(contour_line.size ());
394+
395+ npy_intp vertices_dims[2 ] = {npoints, 2 };
396+ numpy::array_view<double , 2 > vertices (vertices_dims);
397+ double * vertices_ptr = vertices.data ();
398+
399+ npy_intp codes_dims[1 ] = {npoints};
400+ numpy::array_view<unsigned char , 1 > codes (codes_dims);
401+ unsigned char * codes_ptr = codes.data ();
402+
394403 for (ContourLine::const_iterator point = contour_line.begin ();
395- point != contour_line.end (); ++point, ++i) {
396- line (i, 0 ) = point->x ;
397- line (i, 1 ) = point->y ;
404+ point != contour_line.end (); ++point) {
405+ *vertices_ptr++ = point->x ;
406+ *vertices_ptr++ = point->y ;
407+ *codes_ptr++ = (point == contour_line.begin () ? MOVETO : LINETO);
398408 }
399- if (PyList_Append (vertices_list, line.pyobj_steal ())) {
409+
410+ if (contour_line.size () > 1 && contour_line.front () == contour_line.back ())
411+ *(codes_ptr-1 ) = CLOSEPOLY;
412+
413+ if (PyList_Append (vertices_list, vertices.pyobj_steal ()) ||
414+ PyList_Append (codes_list, codes.pyobj_steal ())) {
400415 Py_XDECREF (vertices_list);
401- throw std::runtime_error (" Unable to add contour line to vertices_list" );
416+ Py_XDECREF (codes_list);
417+ throw std::runtime_error (" Unable to add contour line to vertices and codes lists" );
402418 }
403419
404420 contour_line.clear ();
@@ -512,6 +528,12 @@ PyObject* QuadContourGenerator::create_contour(const double& level)
512528 if (vertices_list == 0 )
513529 throw std::runtime_error (" Failed to create Python list" );
514530
531+ PyObject* codes_list = PyList_New (0 );
532+ if (codes_list == 0 ) {
533+ Py_XDECREF (vertices_list);
534+ throw std::runtime_error (" Failed to create Python list" );
535+ }
536+
515537 // Lines that start and end on boundaries.
516538 long ichunk, jchunk, istart, iend, jstart, jend;
517539 for (long ijchunk = 0 ; ijchunk < _chunk_count; ++ijchunk) {
@@ -523,33 +545,33 @@ PyObject* QuadContourGenerator::create_contour(const double& level)
523545 if (EXISTS_NONE (quad) || VISITED (quad,1 )) continue ;
524546
525547 if (BOUNDARY_S (quad) && Z_SW >= 1 && Z_SE < 1 &&
526- start_line (vertices_list, quad, Edge_S, level)) continue ;
548+ start_line (vertices_list, codes_list, quad, Edge_S, level)) continue ;
527549
528550 if (BOUNDARY_W (quad) && Z_NW >= 1 && Z_SW < 1 &&
529- start_line (vertices_list, quad, Edge_W, level)) continue ;
551+ start_line (vertices_list, codes_list, quad, Edge_W, level)) continue ;
530552
531553 if (BOUNDARY_N (quad) && Z_NE >= 1 && Z_NW < 1 &&
532- start_line (vertices_list, quad, Edge_N, level)) continue ;
554+ start_line (vertices_list, codes_list, quad, Edge_N, level)) continue ;
533555
534556 if (BOUNDARY_E (quad) && Z_SE >= 1 && Z_NE < 1 &&
535- start_line (vertices_list, quad, Edge_E, level)) continue ;
557+ start_line (vertices_list, codes_list, quad, Edge_E, level)) continue ;
536558
537559 if (_corner_mask) {
538560 // Equates to NE boundary.
539561 if (EXISTS_SW_CORNER (quad) && Z_SE >= 1 && Z_NW < 1 &&
540- start_line (vertices_list, quad, Edge_NE, level)) continue ;
562+ start_line (vertices_list, codes_list, quad, Edge_NE, level)) continue ;
541563
542564 // Equates to NW boundary.
543565 if (EXISTS_SE_CORNER (quad) && Z_NE >= 1 && Z_SW < 1 &&
544- start_line (vertices_list, quad, Edge_NW, level)) continue ;
566+ start_line (vertices_list, codes_list, quad, Edge_NW, level)) continue ;
545567
546568 // Equates to SE boundary.
547569 if (EXISTS_NW_CORNER (quad) && Z_SW >= 1 && Z_NE < 1 &&
548- start_line (vertices_list, quad, Edge_SE, level)) continue ;
570+ start_line (vertices_list, codes_list, quad, Edge_SE, level)) continue ;
549571
550572 // Equates to SW boundary.
551573 if (EXISTS_NE_CORNER (quad) && Z_NW >= 1 && Z_SE < 1 &&
552- start_line (vertices_list, quad, Edge_SW, level)) continue ;
574+ start_line (vertices_list, codes_list, quad, Edge_SW, level)) continue ;
553575 }
554576 }
555577 }
@@ -581,7 +603,9 @@ PyObject* QuadContourGenerator::create_contour(const double& level)
581603 !ignore_first, &start_quad_edge, 1 , false );
582604 if (ignore_first && !contour_line.empty ())
583605 contour_line.push_back (contour_line.front ());
584- append_contour_line_to_vertices (contour_line, vertices_list);
606+
607+ append_contour_line_to_vertices_and_codes (
608+ contour_line, vertices_list, codes_list);
585609
586610 // Repeat if saddle point but not visited.
587611 if (SADDLE (quad,1 ) && !VISITED (quad,1 ))
@@ -590,7 +614,18 @@ PyObject* QuadContourGenerator::create_contour(const double& level)
590614 }
591615 }
592616
593- return vertices_list;
617+ PyObject* tuple = PyTuple_New (2 );
618+ if (tuple == 0 ) {
619+ Py_XDECREF (vertices_list);
620+ Py_XDECREF (codes_list);
621+ throw std::runtime_error (" Failed to create Python tuple" );
622+ }
623+
624+ // No error checking here as filling in a brand new pre-allocated tuple.
625+ PyTuple_SET_ITEM (tuple, 0 , vertices_list);
626+ PyTuple_SET_ITEM (tuple, 1 , codes_list);
627+
628+ return tuple;
594629}
595630
596631PyObject* QuadContourGenerator::create_filled_contour (const double & lower_level,
@@ -600,13 +635,13 @@ PyObject* QuadContourGenerator::create_filled_contour(const double& lower_level,
600635
601636 Contour contour;
602637
603- PyObject* vertices = PyList_New (0 );
604- if (vertices == 0 )
638+ PyObject* vertices_list = PyList_New (0 );
639+ if (vertices_list == 0 )
605640 throw std::runtime_error (" Failed to create Python list" );
606641
607- PyObject* codes = PyList_New (0 );
608- if (codes == 0 ) {
609- Py_XDECREF (vertices );
642+ PyObject* codes_list = PyList_New (0 );
643+ if (codes_list == 0 ) {
644+ Py_XDECREF (vertices_list );
610645 throw std::runtime_error (" Failed to create Python list" );
611646 }
612647
@@ -637,19 +672,19 @@ PyObject* QuadContourGenerator::create_filled_contour(const double& lower_level,
637672 }
638673
639674 // Create python objects to return for this chunk.
640- append_contour_to_vertices_and_codes (contour, vertices, codes );
675+ append_contour_to_vertices_and_codes (contour, vertices_list, codes_list );
641676 }
642677
643678 PyObject* tuple = PyTuple_New (2 );
644679 if (tuple == 0 ) {
645- Py_XDECREF (vertices );
646- Py_XDECREF (codes );
680+ Py_XDECREF (vertices_list );
681+ Py_XDECREF (codes_list );
647682 throw std::runtime_error (" Failed to create Python tuple" );
648683 }
649684
650685 // No error checking here as filling in a brand new pre-allocated tuple.
651- PyTuple_SET_ITEM (tuple, 0 , vertices );
652- PyTuple_SET_ITEM (tuple, 1 , codes );
686+ PyTuple_SET_ITEM (tuple, 0 , vertices_list );
687+ PyTuple_SET_ITEM (tuple, 1 , codes_list );
653688
654689 return tuple;
655690}
@@ -1740,7 +1775,8 @@ ContourLine* QuadContourGenerator::start_filled(
17401775}
17411776
17421777bool QuadContourGenerator::start_line (
1743- PyObject* vertices_list, long quad, Edge edge, const double & level)
1778+ PyObject* vertices_list, PyObject* codes_list, long quad, Edge edge,
1779+ const double & level)
17441780{
17451781 assert (vertices_list != 0 && " Null python vertices list" );
17461782 assert (is_edge_a_boundary (QuadEdge (quad, edge)) &&
@@ -1749,7 +1785,10 @@ bool QuadContourGenerator::start_line(
17491785 QuadEdge quad_edge (quad, edge);
17501786 ContourLine contour_line (false );
17511787 follow_interior (contour_line, quad_edge, 1 , level, true , 0 , 1 , false );
1752- append_contour_line_to_vertices (contour_line, vertices_list);
1788+
1789+ append_contour_line_to_vertices_and_codes (
1790+ contour_line, vertices_list, codes_list);
1791+
17531792 return VISITED (quad,1 );
17541793}
17551794
0 commit comments