@@ -381,24 +381,40 @@ QuadContourGenerator::~QuadContourGenerator()
381
381
delete [] _cache;
382
382
}
383
383
384
- void QuadContourGenerator::append_contour_line_to_vertices (
384
+ void QuadContourGenerator::append_contour_line_to_vertices_and_codes (
385
385
ContourLine& contour_line,
386
- PyObject* vertices_list) const
386
+ PyObject* vertices_list,
387
+ PyObject* codes_list) const
387
388
{
388
389
assert (vertices_list != 0 && " Null python vertices_list" );
390
+ assert (codes_list != 0 && " Null python codes_list" );
389
391
390
392
// 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
+
394
403
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);
398
408
}
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 ())) {
400
415
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" );
402
418
}
403
419
404
420
contour_line.clear ();
@@ -512,6 +528,12 @@ PyObject* QuadContourGenerator::create_contour(const double& level)
512
528
if (vertices_list == 0 )
513
529
throw std::runtime_error (" Failed to create Python list" );
514
530
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
+
515
537
// Lines that start and end on boundaries.
516
538
long ichunk, jchunk, istart, iend, jstart, jend;
517
539
for (long ijchunk = 0 ; ijchunk < _chunk_count; ++ijchunk) {
@@ -523,33 +545,33 @@ PyObject* QuadContourGenerator::create_contour(const double& level)
523
545
if (EXISTS_NONE (quad) || VISITED (quad,1 )) continue ;
524
546
525
547
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 ;
527
549
528
550
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 ;
530
552
531
553
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 ;
533
555
534
556
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 ;
536
558
537
559
if (_corner_mask) {
538
560
// Equates to NE boundary.
539
561
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 ;
541
563
542
564
// Equates to NW boundary.
543
565
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 ;
545
567
546
568
// Equates to SE boundary.
547
569
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 ;
549
571
550
572
// Equates to SW boundary.
551
573
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 ;
553
575
}
554
576
}
555
577
}
@@ -581,7 +603,9 @@ PyObject* QuadContourGenerator::create_contour(const double& level)
581
603
!ignore_first, &start_quad_edge, 1 , false );
582
604
if (ignore_first && !contour_line.empty ())
583
605
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);
585
609
586
610
// Repeat if saddle point but not visited.
587
611
if (SADDLE (quad,1 ) && !VISITED (quad,1 ))
@@ -590,7 +614,18 @@ PyObject* QuadContourGenerator::create_contour(const double& level)
590
614
}
591
615
}
592
616
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;
594
629
}
595
630
596
631
PyObject* QuadContourGenerator::create_filled_contour (const double & lower_level,
@@ -600,13 +635,13 @@ PyObject* QuadContourGenerator::create_filled_contour(const double& lower_level,
600
635
601
636
Contour contour;
602
637
603
- PyObject* vertices = PyList_New (0 );
604
- if (vertices == 0 )
638
+ PyObject* vertices_list = PyList_New (0 );
639
+ if (vertices_list == 0 )
605
640
throw std::runtime_error (" Failed to create Python list" );
606
641
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 );
610
645
throw std::runtime_error (" Failed to create Python list" );
611
646
}
612
647
@@ -637,19 +672,19 @@ PyObject* QuadContourGenerator::create_filled_contour(const double& lower_level,
637
672
}
638
673
639
674
// 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 );
641
676
}
642
677
643
678
PyObject* tuple = PyTuple_New (2 );
644
679
if (tuple == 0 ) {
645
- Py_XDECREF (vertices );
646
- Py_XDECREF (codes );
680
+ Py_XDECREF (vertices_list );
681
+ Py_XDECREF (codes_list );
647
682
throw std::runtime_error (" Failed to create Python tuple" );
648
683
}
649
684
650
685
// 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 );
653
688
654
689
return tuple;
655
690
}
@@ -1740,7 +1775,8 @@ ContourLine* QuadContourGenerator::start_filled(
1740
1775
}
1741
1776
1742
1777
bool 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)
1744
1780
{
1745
1781
assert (vertices_list != 0 && " Null python vertices list" );
1746
1782
assert (is_edge_a_boundary (QuadEdge (quad, edge)) &&
@@ -1749,7 +1785,10 @@ bool QuadContourGenerator::start_line(
1749
1785
QuadEdge quad_edge (quad, edge);
1750
1786
ContourLine contour_line (false );
1751
1787
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
+
1753
1792
return VISITED (quad,1 );
1754
1793
}
1755
1794
0 commit comments