@@ -640,56 +640,42 @@ SEXP LAS::find_polygon_ids(Rcpp::List polygons, bool by_poly)
640640 std::fill (poly_id.begin (), poly_id.end (), NA_INTEGER);
641641 }
642642
643- SpatialIndex tree (las);
643+ if (polygons.size () == 0 )
644+ Rcpp::stop (" 0 size input" );
644645
645- for ( unsigned int i = 0 ; i < polygons.size () ; i++ )
646+ if ( polygons.size () == 1 )
646647 {
647- bool is_in_polygon = false ;
648-
649- // This list can be made of several rings (MULTIPOLYGON) and interior rings
650- Rcpp::List rings = polygons[i];
648+ // "Stupid algo": test every point against the single polygon
649+ Rcpp::List rings = polygons[0 ];
651650
652- // Find the bbox of the polygons
653- double min_x = INFINITY;
654- double min_y = INFINITY;
655- double max_x = -INFINITY;
656- double max_y = -INFINITY;
657- for (int j = 0 ; j < rings.size () ; j++)
651+ // Compute bounding box
652+ double min_x = INFINITY, min_y = INFINITY;
653+ double max_x = -INFINITY, max_y = -INFINITY;
654+ for (int j = 0 ; j < rings.size (); j++)
658655 {
659656 Rcpp::NumericMatrix ring = rings[j];
660657 Rcpp::NumericVector x = ring (_, 0 );
661658 Rcpp::NumericVector y = ring (_, 1 );
662659
663- double maxx = max (x);
664- double maxy = max (y);
665- double minx = min (x);
666- double miny = min (y);
667-
668- if (min_x > minx) min_x = minx;
669- if (min_y > miny) min_y = miny;
670- if (max_x < maxx) max_x = maxx;
671- if (max_y < maxy) max_y = maxy;
660+ min_x = std::min (min_x, (double )min (x));
661+ min_y = std::min (min_y, (double )min (y));
662+ max_x = std::max (max_x, (double )max (x));
663+ max_y = std::max (max_y, (double )max (y));
672664 }
673665
674- // Spatial query of the point that are in the bounding box of the polygon
675- lidR::Rectangle rect (min_x, max_x, min_y, max_y);
676- std::vector<PointXYZ> pts;
677- tree.lookup (rect, pts);
678-
679- // For each point we check if it is in the potential multi part polygon
680- for (unsigned int k = 0 ; k < pts.size () ; k++)
666+ for (size_t pid = 0 ; pid < X.size (); pid++)
681667 {
668+ // Bounding box test
669+ if (X[pid] < min_x || X[pid] > max_x || Y[pid] < min_y || Y[pid] > max_y)
670+ continue ;
671+
682672 bool inpoly = false ;
683673
684- // Loop through sub polygons (ring)
685- for (int j = 0 ; j < rings.size () ; j++)
674+ for (int j = 0 ; j < rings.size (); j++)
686675 {
687676 Rcpp::NumericMatrix ring = rings[j];
688-
689- // We need to know if the ring is an exterior/interior ring (hole)
690- bool exterior_ring = ring (0 ,2 ) == 1 ;
691-
692- bool b = pnpoly (ring, pts[k].x , pts[k].y );
677+ bool exterior_ring = ring (0 , 2 ) == 1 ;
678+ bool b = pnpoly (ring, X[pid], Y[pid]);
693679
694680 if (b)
695681 {
@@ -708,9 +694,68 @@ SEXP LAS::find_polygon_ids(Rcpp::List polygons, bool by_poly)
708694 if (inpoly)
709695 {
710696 if (by_poly)
711- res[i ].push_back (pts[k]. id + 1 );
697+ res[0 ].push_back (pid + 1 );
712698 else
713- poly_id[pts[k].id ] = i+1 ;
699+ poly_id[pid] = 1 ;
700+ }
701+ }
702+ }
703+ else
704+ {
705+ // Usual algo with spatial index
706+ GridPartition tree (las);
707+
708+ for (unsigned int i = 0 ; i < polygons.size () ; i++)
709+ {
710+ Rcpp::List rings = polygons[i];
711+
712+ // Find bbox
713+ double min_x = INFINITY, min_y = INFINITY;
714+ double max_x = -INFINITY, max_y = -INFINITY;
715+ for (int j = 0 ; j < rings.size () ; j++)
716+ {
717+ Rcpp::NumericMatrix ring = rings[j];
718+ Rcpp::NumericVector x = ring (_, 0 );
719+ Rcpp::NumericVector y = ring (_, 1 );
720+
721+ min_x = std::min (min_x, (double )min (x));
722+ min_y = std::min (min_y, (double )min (y));
723+ max_x = std::max (max_x, (double )max (x));
724+ max_y = std::max (max_y, (double )max (y));
725+ }
726+
727+ lidR::Rectangle rect (min_x, max_x, min_y, max_y);
728+ std::vector<PointXYZ> pts;
729+ tree.lookup (rect, pts);
730+
731+ for (unsigned int k = 0 ; k < pts.size () ; k++)
732+ {
733+ bool inpoly = false ;
734+ for (int j = 0 ; j < rings.size () ; j++)
735+ {
736+ Rcpp::NumericMatrix ring = rings[j];
737+ bool exterior_ring = ring (0 , 2 ) == 1 ;
738+ bool b = pnpoly (ring, pts[k].x , pts[k].y );
739+
740+ if (b)
741+ {
742+ if (exterior_ring)
743+ inpoly = true ;
744+ else
745+ {
746+ inpoly = false ;
747+ break ;
748+ }
749+ }
750+ }
751+
752+ if (inpoly)
753+ {
754+ if (by_poly)
755+ res[i].push_back (pts[k].id + 1 );
756+ else
757+ poly_id[pts[k].id ] = i + 1 ;
758+ }
714759 }
715760 }
716761 }
0 commit comments