/** \brief Select features by polygon \param[in] Map vector map \param[in] type feature type \param[in] poly polygon coordinates \param[in,out] List list of selected features \return number of selected lines */ int sel_by_polygon(struct Map_info *Map, int type, struct line_pnts *Polygon, struct ilist *List) { struct ilist *List_tmp; if (first_selection) { List_tmp = List; first_selection = 0; } else { List_tmp = Vect_new_list(); } /* no isles */ Vect_select_lines_by_polygon(Map, Polygon, 0, NULL, type, List_tmp); G_debug(1, " %d lines selected (by polygon)", List_tmp->n_values); /* merge lists (only duplicate items) */ if (List_tmp != List) { merge_lists(List, List_tmp); Vect_destroy_list(List_tmp); } return List->n_values; }
/** \brief Select features by coordinates \param[in] Map vector map \param[in] type feature type \param[in] coords coordinates GRASS parameters \param[in] thresh threshold value for searching \param[in,out] List list of selected features \return number of selected lines */ int sel_by_coordinates(struct Map_info *Map, int type, struct line_pnts *coords, double thresh, struct ilist *List) { int i; double east, north, maxdist; struct ilist *List_tmp, *List_in_box; struct line_pnts *box; if (first_selection) { List_tmp = List; first_selection = 0; } else { List_tmp = Vect_new_list(); } box = Vect_new_line_struct(); List_in_box = Vect_new_list(); if (thresh < 0) maxdist = max_distance(thresh); else maxdist = thresh; for (i = 0; i < coords->n_points; i++) { east = coords->x[i]; north = coords->y[i]; coord2bbox(east, north, maxdist, box); Vect_select_lines_by_polygon(Map, box, 0, NULL, type, List_in_box); if (List_in_box->n_values > 0) Vect_list_append_list(List_tmp, List_in_box); } G_debug(1, " %d lines selected (by coordinates)", List_tmp->n_values); /* merge lists (only duplicate items) */ if (List_tmp != List) { merge_lists(List, List_tmp); Vect_destroy_list(List_tmp); } Vect_destroy_line_struct(box); Vect_destroy_list(List_in_box); return List->n_values; }
void QgsGrassFeatureIterator::setSelectionRect( const QgsRectangle& rect, bool useIntersect ) { QgsDebugMsg( QString( "useIntersect = %1 rect = %2" ).arg( useIntersect ).arg( rect.toString() ) ); // TODO: selection of edited lines // Lock because functions using static/global variables are used // (e.g. static LocList in Vect_select_lines_by_box, global BranchBuf in RTreeGetBranches) QgsGrass::lock(); mSelection.fill( false ); BOUND_BOX box; box.N = rect.yMaximum(); box.S = rect.yMinimum(); box.E = rect.xMaximum(); box.W = rect.xMinimum(); box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; // Init structures struct ilist * list = Vect_new_list(); if ( !useIntersect ) { // select by bounding boxes only if ( mSource->mLayerType == QgsGrassProvider::POINT || mSource->mLayerType == QgsGrassProvider::CENTROID || mSource->mLayerType == QgsGrassProvider::LINE || mSource->mLayerType == QgsGrassProvider::FACE || mSource->mLayerType == QgsGrassProvider::BOUNDARY || mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE || mSource->mEditing ) { QgsDebugMsg( "Vect_select_lines_by_box" ); int type = mSource->mGrassType; if ( mSource->mEditing ) { type = GV_POINTS | GV_LINES; } QgsDebugMsg( QString( "type = %1" ).arg( type ) ); Vect_select_lines_by_box( mSource->map(), &box, type, list ); } else if ( mSource->mLayerType == QgsGrassProvider::POLYGON ) { Vect_select_areas_by_box( mSource->map(), &box, list ); } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { Vect_select_nodes_by_box( mSource->map(), &box, list ); } } else { // check intersection struct line_pnts *polygon = Vect_new_line_struct(); // Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is // using dig_line_box to get the box, it is not perfect, Vect_select_lines_by_polygon // should clarify better how 2D/3D is treated Vect_append_point( polygon, rect.xMinimum(), rect.yMinimum(), -PORT_DOUBLE_MAX ); Vect_append_point( polygon, rect.xMaximum(), rect.yMinimum(), PORT_DOUBLE_MAX ); Vect_append_point( polygon, rect.xMaximum(), rect.yMaximum(), 0 ); Vect_append_point( polygon, rect.xMinimum(), rect.yMaximum(), 0 ); Vect_append_point( polygon, rect.xMinimum(), rect.yMinimum(), 0 ); if ( mSource->mLayerType == QgsGrassProvider::POINT || mSource->mLayerType == QgsGrassProvider::CENTROID || mSource->mLayerType == QgsGrassProvider::LINE || mSource->mLayerType == QgsGrassProvider::FACE || mSource->mLayerType == QgsGrassProvider::BOUNDARY || mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE || mSource->mEditing ) { QgsDebugMsg( "Vect_select_lines_by_polygon" ); int type = mSource->mGrassType; if ( mSource->mEditing ) { type = GV_POINTS | GV_LINES; } QgsDebugMsg( QString( "type = %1" ).arg( type ) ); Vect_select_lines_by_polygon( mSource->map(), polygon, 0, NULL, type, list ); } else if ( mSource->mLayerType == QgsGrassProvider::POLYGON ) { Vect_select_areas_by_polygon( mSource->map(), polygon, 0, NULL, list ); } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { // There is no Vect_select_nodes_by_polygon but for nodes it is the same as by box Vect_select_nodes_by_box( mSource->map(), &box, list ); } Vect_destroy_line_struct( polygon ); } for ( int i = 0; i < list->n_values; i++ ) { int lid = list->value[i]; if ( lid < 1 || lid >= mSelection.size() ) // should not happen { QgsDebugMsg( QString( "lid %1 out of range <1,%2>" ).arg( lid ).arg( mSelection.size() ) ); continue; } mSelection.setBit( lid ); } Vect_destroy_list( list ); QgsDebugMsg( QString( " %1 features selected" ).arg( list->n_values ) ); QgsGrass::unlock(); }
void QgsGrassFeatureIterator::setSelectionRect( const QgsRectangle& rect, bool useIntersect ) { //apply selection rectangle resetSelection( 0 ); BOUND_BOX box; box.N = rect.yMaximum(); box.S = rect.yMinimum(); box.E = rect.xMaximum(); box.W = rect.xMinimum(); box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; if ( !useIntersect ) { // select by bounding boxes only if ( mSource->mLayerType == QgsGrassProvider::POINT || mSource->mLayerType == QgsGrassProvider::CENTROID || mSource->mLayerType == QgsGrassProvider::LINE || mSource->mLayerType == QgsGrassProvider::FACE || mSource->mLayerType == QgsGrassProvider::BOUNDARY || mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { Vect_select_lines_by_box( mSource->mMap, &box, mSource->mGrassType, mList ); } else if ( mSource->mLayerType == QgsGrassProvider::POLYGON ) { Vect_select_areas_by_box( mSource->mMap, &box, mList ); } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { Vect_select_nodes_by_box( mSource->mMap, &box, mList ); } } else { // check intersection struct line_pnts *Polygon; Polygon = Vect_new_line_struct(); // Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is // using dig_line_box to get the box, it is not perfect, Vect_select_lines_by_polygon // should clarify better how 2D/3D is treated Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), -PORT_DOUBLE_MAX ); Vect_append_point( Polygon, rect.xMaximum(), rect.yMinimum(), PORT_DOUBLE_MAX ); Vect_append_point( Polygon, rect.xMaximum(), rect.yMaximum(), 0 ); Vect_append_point( Polygon, rect.xMinimum(), rect.yMaximum(), 0 ); Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), 0 ); if ( mSource->mLayerType == QgsGrassProvider::POINT || mSource->mLayerType == QgsGrassProvider::CENTROID || mSource->mLayerType == QgsGrassProvider::LINE || mSource->mLayerType == QgsGrassProvider::FACE || mSource->mLayerType == QgsGrassProvider::BOUNDARY || mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { Vect_select_lines_by_polygon( mSource->mMap, Polygon, 0, NULL, mSource->mGrassType, mList ); } else if ( mSource->mLayerType == QgsGrassProvider::POLYGON ) { Vect_select_areas_by_polygon( mSource->mMap, Polygon, 0, NULL, mList ); } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { // There is no Vect_select_nodes_by_polygon but for nodes it is the same as by box Vect_select_nodes_by_box( mSource->mMap, &box, mList ); } Vect_destroy_line_struct( Polygon ); } for ( int i = 0; i < mList->n_values; i++ ) { if ( mList->value[i] <= mSelectionSize ) { mSelection[mList->value[i]] = 1; } else { QgsDebugMsg( "Selected element out of range" ); } } }
/*! \brief Merge lines/boundaries At least two lines need to be given. \param Map pointer to Map_info \param List list of selected lines \return number of merged lines \return -1 on error */ int Vedit_merge_lines(struct Map_info *Map, struct ilist *List) { struct ilist *List_in_box; struct line_pnts *Points1, *Points2, *Points; struct line_cats *Cats1, *Cats2; int line_i, i, j; int line, line1, type1, line2; int do_merge; /* number of lines (original, selected, merged) */ int nlines, nlines_merged; nlines_merged = 0; if (List->n_values < 2) { return 0; } Points1 = Vect_new_line_struct(); Cats1 = Vect_new_cats_struct(); Points2 = Vect_new_line_struct(); Cats2 = Vect_new_cats_struct(); Points = Vect_new_line_struct(); List_in_box = Vect_new_list(); nlines = Vect_get_num_lines(Map); /* merge lines */ for (line_i = 0; line_i < List->n_values; line_i++) { line1 = List->value[line_i]; if (!Vect_line_alive(Map, line1)) continue; type1 = Vect_read_line(Map, Points1, Cats1, line1); if (!(type1 & GV_LINES)) continue; Vect_reset_line(Points); for (i = 0; i < Points1->n_points; i += Points1->n_points - 1) { Vect_reset_list(List_in_box); /* define searching region */ Vect_reset_line(Points2); /* Vect_append_point (Points2, Points1 -> x[i] - thresh, Points1 -> y[i] + thresh, Points1 -> z[i]); Vect_append_point (Points2, Points1 -> x[i] + thresh, Points1 -> y[i] + thresh, Points1 -> z[i]); Vect_append_point (Points2, Points1 -> x[i] + thresh, Points1 -> y[i] - thresh, Points1 -> z[i]); Vect_append_point (Points2, Points1 -> x[i] - thresh, Points1 -> y[i] - thresh, Points1 -> z[i]); */ Vect_append_point(Points2, Points1->x[i], Points1->y[i], Points1->z[i]); /* * merge lines only if two lines found in the region * i.e. the current line and an adjacent line */ if (1 < Vect_select_lines_by_polygon(Map, Points2, 0, NULL, GV_LINES, List_in_box)) { do_merge = 1; line2 = -1; for (j = 0; do_merge && j < List->n_values; j++) { if (List->value[j] == line1 || !Vect_line_alive(Map, List->value[j])) continue; if (Vect_val_in_list(List_in_box, List->value[j])) { if (line2 > 0) { /* three lines found * selected lines will be not merged */ do_merge = 0; } else { line2 = List->value[j]; } } } if (!do_merge || line2 < 0) continue; Vect_read_line(Map, Points2, Cats2, line2); merge_lines(Points1, Cats1, Points2, Cats2, -1.0, &Points); /* do not use threshold value */ G_debug(3, "Vedit_merge_lines(): lines=%d,%d", line1, line2); if (Points->n_points > 0) { if (Vect_delete_line(Map, line2) == -1) { return -1; } if (line2 <= nlines) nlines_merged++; } } } /* for each node */ if (Points->n_points > 0) { line = Vect_rewrite_line(Map, line1, type1, Points, Cats1); if (line < 0) { return -1; } if (line1 <= nlines) nlines_merged++; /* update number of lines */ Vect_list_append(List, line); } } /* for each line */ /* destroy stuctures */ Vect_destroy_line_struct(Points1); Vect_destroy_line_struct(Points2); Vect_destroy_line_struct(Points); Vect_destroy_cats_struct(Cats1); Vect_destroy_cats_struct(Cats2); return nlines_merged; }