[GRASS-SVN] r32029 - grass-addons/vector/v.parallel2
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Jul 6 14:06:52 EDT 2008
Author: rmatev
Date: 2008-07-06 14:06:51 -0400 (Sun, 06 Jul 2008)
New Revision: 32029
Modified:
grass-addons/vector/v.parallel2/vlib_buffer.c
Log:
Partially implemented removal of extra loops
Modified: grass-addons/vector/v.parallel2/vlib_buffer.c
===================================================================
--- grass-addons/vector/v.parallel2/vlib_buffer.c 2008-07-06 14:33:01 UTC (rev 32028)
+++ grass-addons/vector/v.parallel2/vlib_buffer.c 2008-07-06 18:06:51 UTC (rev 32029)
@@ -1,4 +1,4 @@
-/* Functions: nearest, adjust_line, parallel_line
+/* Functions: ...
**
** Author: Radim Blazek, Rosen Matev; June 2008
**
@@ -50,210 +50,6 @@
*y = dy/l;
}
-/* find_cross find first crossing between segments from s1 to s2 and from s3 to s4
-** s5 is set to first segment and s6 to second
-** neighbours are taken as crossing each other only if overlap
-** returns: 1 found
-** -1 found overlap
-** 0 not found
-*/
-int find_cross ( struct line_pnts *Points, int s1, int s2, int s3, int s4, int *s5, int *s6 )
-{
- int i, j, np, ret;
- double *x, *y;
-
- G_debug (5, "find_cross(): npoints = %d, s1 = %d, s2 = %d, s3 = %d, s4 = %d",
- Points->n_points, s1, s2, s3, s4 );
-
- x = Points->x;
- y = Points->y;
- np = Points->n_points;
-
- for ( i=s1; i<=s2; i++)
- {
- for ( j=s3; j<=s4; j++)
- {
- if ( j==i ){
- continue;
- }
- ret = dig_test_for_intersection ( x[i], y[i], x[i+1], y[i+1], x[j], y[j], x[j+1], y[j+1] );
- if ( ret == 1 && ( (i-j) > 1 || (i-j) < -1 ) )
- {
- *s5 = i;
- *s6 = j;
- G_debug (5, " intersection: s5 = %d, s6 = %d", *s5, *s6 );
- return 1;
- }
- if ( ret == -1 )
- {
- *s5 = i;
- *s6 = j;
- G_debug (5, " overlap: s5 = %d, s6 = %d", *s5, *s6 );
- return -1;
- }
- }
- }
- G_debug (5, " no intersection" );
- return 0;
-}
-
-/* point_in_buf - test if point px,py is in d buffer of Points
-** returns: 1 in buffer
-** 0 not in buffer
-*/
-int point_in_buf ( struct line_pnts *Points, double px, double py, double d )
-{
- int i, np;
- double sd;
-
- np = Points->n_points;
- d *= d;
- for ( i=0; i < np-1; i++)
- {
- sd = dig_distance2_point_to_line ( px, py, 0,
- Points->x[i], Points->y[i], 0, Points->x[i+1], Points->y[i+1], 0,
- 0, NULL, NULL, NULL, NULL, NULL );
- if ( sd <= d )
- {
- return 1;
- }
- }
- return 0;
-}
-
-/* clean_parallel - clean parallel line created by parallel_line:
-** - looking for loops and if loop doesn't contain any other loop
-** and centroid of loop is in buffer removes this loop (repeated)
-** - optionaly removes all end points in buffer
-* parameters:
-* Points - parallel line
-* origPoints - original line
-* d - offset
-* rm_end - remove end points in buffer
-** note1: on some lines (multiply selfcrossing; lines with end points
-** in buffer of line other; some shapes of ends ) may create nosense
-** note2: this function is stupid and slow, somebody more clever
-** than I am should write paralle_line + clean_parallel
-** better; RB March 2000
-*/
-void clean_parallel ( struct line_pnts *Points, struct line_pnts *origPoints, double d , int rm_end )
-{
- int i, j, np, npn, sa, sb;
- int sa_max = 0;
- int first=0, current, last, lcount;
- double *x, *y, px, py, ix, iy;
- static struct line_pnts *sPoints = NULL;
-
- G_debug (4, "clean_parallel(): npoints = %d, d = %f, rm_end = %d", Points->n_points, d, rm_end );
-
- x = Points->x;
- y = Points->y;
- np = Points->n_points;
-
- if ( sPoints == NULL )
- sPoints = Vect_new_line_struct();
-
- Vect_reset_line ( sPoints );
-
- npn=1;
-
- /* remove loops */
- while( first < np-2 ){
- /* find first loop which doesn't contain any other loop */
- current=first; last=Points->n_points-2; lcount=0;
- while( find_cross ( Points, current, last-1, current+1, last, &sa, &sb ) != 0 )
- {
- if ( lcount == 0 ){ first=sa; } /* move first forward */
-
- current=sa+1;
- last=sb;
- lcount++;
- G_debug (5, " current = %d, last = %d, lcount = %d", current, last, lcount);
- }
- if ( lcount == 0 ) { break; } /* loop not found */
-
- /* ensure sa is monotonically increasing, so npn doesn't reset low */
- if (sa > sa_max ) sa_max = sa;
- if (sa < sa_max ) break;
-
- /* remove loop if in buffer */
- if ( (sb-sa) == 1 ){ /* neighbouring lines overlap */
- j=sb+1;
- npn=sa+1;
- } else {
- Vect_reset_line ( sPoints );
- dig_find_intersection ( x[sa],y[sa],x[sa+1],y[sa+1],x[sb],y[sb],x[sb+1],y[sb+1], &ix,&iy);
- Vect_append_point ( sPoints, ix, iy, 0 );
- for ( i=sa+1 ; i < sb+1; i++ ) { /* create loop polygon */
- Vect_append_point ( sPoints, x[i], y[i], 0 );
- }
- Vect_find_poly_centroid ( sPoints, &px, &py);
- if ( point_in_buf( origPoints, px, py, d ) ){ /* is loop in buffer ? */
- npn=sa+1;
- x[npn] = ix;
- y[npn] = iy;
- j=sb+1;
- npn++;
- if ( lcount == 0 ){ first=sb; }
- } else { /* loop is not in buffer */
- first=sb;
- continue;
- }
- }
-
- for (i=j;i<Points->n_points;i++) /* move points down */
- {
- x[npn] = x[i];
- y[npn] = y[i];
- npn++;
- }
- Points->n_points=npn;
- }
-
- if ( rm_end ) {
- /* remove points from start in buffer */
- j=0;
- for (i=0;i<Points->n_points-1;i++)
- {
- px=(x[i]+x[i+1])/2;
- py=(y[i]+y[i+1])/2;
- if ( point_in_buf ( origPoints, x[i], y[i], d*0.9999)
- && point_in_buf ( origPoints, px, py, d*0.9999) ){
- j++;
- } else {
- break;
- }
- }
- if (j>0){
- npn=0;
- for (i=j;i<Points->n_points;i++)
- {
- x[npn] = x[i];
- y[npn] = y[i];
- npn++;
- }
- Points->n_points = npn;
- }
- /* remove points from end in buffer */
- j=0;
- for (i=Points->n_points-1 ;i>=1; i--)
- {
- px=(x[i]+x[i-1])/2;
- py=(y[i]+y[i-1])/2;
- if ( point_in_buf ( origPoints, x[i], y[i], d*0.9999)
- && point_in_buf ( origPoints, px, py, d*0.9999) ){
- j++;
- } else {
- break;
- }
- }
- if (j>0){
- Points->n_points -= j;
- }
- }
-}
-
-
static void rotate_vector(double x, double y, double cosa, double sina, double *nx, double *ny) {
*nx = x*cosa - y*sina;
*ny = x*sina + y*cosa;
@@ -261,7 +57,7 @@
}
/*
-* (x, y) shoud be normalized vector for common transforms; This func transforms it to a vector corresponding to da, db, dalpha params
+* (x,y) shoud be normalized vector for common transforms; This func transforms (x,y) to a vector corresponding to da, db, dalpha params
*/
static void elliptic_transform(double x, double y, double da, double db, double dalpha, double *nx, double *ny) {
double cosa = cos(dalpha);
@@ -579,8 +375,8 @@
}
/*
-* IMPORTANT: split_at_intersections() must be applied to input line before calling extract_contour
-* when visited != NULL, extract_contour() marks the sides of lines as visited along the contour
+* IMPORTANT: split_at_intersections() must be applied to input line before calling extract_contour().
+* When visited != NULL, extract_contour() marks the sides of lines as visited along the contour.
* visited->a must have at least Points->n_points elements
*
* side: side >= 0 - right contour, side < 0 - left contour
@@ -801,7 +597,7 @@
return 0;
}
-void parallel_line_b(struct line_pnts *Points, double da, double db, double dalpha, int round, int caps, double tol, struct line_pnts **oPoints, struct line_pnts ***iPoints, int *inner_count) {
+void extract_all_inner_contours(struct line_pnts *Points, struct line_pnts ***iPoints, int *inner_count) {
struct line_pnts *Points2, *tPoints;
struct line_pnts **arrPoints;
int i, side, count;
@@ -809,7 +605,7 @@
int allocated = more;
struct visited_segments visited;
- G_debug(4, "parallel_line_b()");
+ G_debug(4, "extract_all_inner_contours()");
/* initializations and spliting of the input line */
tPoints = Vect_new_line_struct();
@@ -821,10 +617,8 @@
arrPoints = G_malloc(allocated*sizeof(struct line_pnts *));
- /* outer contour */
+ /* extract outer contour so that we have filled visited appropriately */
side = extract_outer_contour(Points2, 0, tPoints, &visited);
- *oPoints = Vect_new_line_struct();
- parallel_line(tPoints, da, db, dalpha, side, round, caps, LOOPED_LINE, tol, *oPoints);
/* inner contours */
count = 0;
@@ -835,8 +629,7 @@
arrPoints = G_realloc(arrPoints, allocated*sizeof(struct line_pnts *));
}
arrPoints[count] = Vect_new_line_struct();
-/* Vect_copy_xyz_to_pnts(arrPoints[count], tPoints->x, tPoints->y, tPoints->z, tPoints->n_points); */
- parallel_line(tPoints, da, db, dalpha, side, round, caps, LOOPED_LINE, tol, arrPoints[count]);
+ Vect_copy_xyz_to_pnts(arrPoints[count], tPoints->x, tPoints->y, tPoints->z, tPoints->n_points);
count++;
side = extract_inner_contour(Points2, tPoints, &visited);
@@ -850,6 +643,135 @@
Vect_destroy_line_struct(tPoints);
Vect_destroy_line_struct(Points2);
+ return;
+}
+
+/* point_in_buf - test if point px,py is in d buffer of Points
+** returns: 1 in buffer
+** 0 not in buffer
+*/
+int point_in_buf(struct line_pnts *Points, double px, double py, double da, double db, double dalpha) {
+ int i, np;
+ double cosa = cos(dalpha);
+ double sina = sin(dalpha);
+ double delta, delta_k;
+ double vx, vy, wx, wy, mx, my, nx, ny;
+ double k, t, tx, ty, d, da2;
+
+ np = Points->n_points;
+ da2 = da*da;
+ for (i = 0; i < np-1; i++) {
+ vx = Points->x[i];
+ vy = Points->y[i];
+ wx = Points->x[i+1];
+ wy = Points->y[i+1];
+
+ if (da != db) {
+ mx = wx - vx;
+ my = wy - vy;
+
+ delta = mx*sina - my*cosa;
+ if (delta == 0) {
+ t = da; da = db; db = t;
+ dalpha = dalpha + M_PI_2;
+ cosa = cos(dalpha);
+ sina = sin(dalpha);
+ delta = mx*sina - my*cosa;
+ }
+ delta_k = (px-vx)*sina - (py-vy)*cosa;
+ k = delta_k/delta;
+ nx = px - vx - k*mx;
+ ny = py - vy - k*my;
+
+ /* inverse transform */
+ elliptic_transform(nx, ny, 1/da, 1/db, dalpha, &tx, &ty);
+
+ d = dig_distance2_point_to_line(tx, ty, 0, vx, vy, 0, wx, wy, 0,
+ 0, NULL, NULL, NULL, NULL, NULL);
+ if (d <= 1)
+ return 1;
+ }
+ else {
+ d = dig_distance2_point_to_line(px, py, 0, vx, vy, 0, wx, wy, 0,
+ 0, NULL, NULL, NULL, NULL, NULL);
+ if (d <= da2) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void parallel_line_b(struct line_pnts *Points, double da, double db, double dalpha, int round, int caps, double tol, struct line_pnts **oPoints, struct line_pnts ***iPoints, int *inner_count) {
+ struct line_pnts *Points2, *tPoints, *sPoints;
+ struct line_pnts **arrPoints;
+ struct line_pnts **arrPoints2;
+ int i, side, count, count2;
+ int res;
+ int more = 8;
+ int allocated = more;
+ double px, py;
+ struct visited_segments visited;
+
+ G_debug(4, "parallel_line_b()");
+
+ /* initializations and spliting of the input line */
+ tPoints = Vect_new_line_struct();
+ sPoints = Vect_new_line_struct();
+ Points2 = Vect_new_line_struct();
+ split_at_intersections(Points, Points2);
+
+ visited.a = (char *)G_malloc(sizeof(char)*Points2->n_points);
+ memset(visited.a, 0, sizeof(char)*Points2->n_points);
+
+ arrPoints = G_malloc(allocated*sizeof(struct line_pnts *));
+
+ /* outer contour */
+ side = extract_outer_contour(Points2, 0, tPoints, &visited);
+ *oPoints = Vect_new_line_struct();
+ parallel_line(tPoints, da, db, dalpha, side, round, caps, LOOPED_LINE, tol, *oPoints);
+
+ /* inner contours */
+ count = 0;
+ side = extract_inner_contour(Points2, tPoints, &visited);
+ while (side != 0) {
+ parallel_line(tPoints, da, db, dalpha, side, round, caps, LOOPED_LINE, tol, sPoints);
+
+ extract_all_inner_contours(sPoints, &arrPoints2, &count2);
+
+ for (i = 0; i < count2; i++) {
+ res = Vect_line_check_intersection(tPoints, arrPoints2[i], 0);
+ if (res != 0)
+ continue;
+
+ res = Vect_get_point_in_poly(arrPoints2[i], &px, &py);
+ if (res != 0)
+ G_fatal_error("Vect_get_point_in_poly() failed.");
+ if (point_in_buf(tPoints, px, py, da, db, dalpha))
+ continue;
+
+ /* passed all tests, add new island */
+ if (allocated < count+1) {
+ allocated += more;
+ arrPoints = G_realloc(arrPoints, allocated*sizeof(struct line_pnts *));
+ }
+ arrPoints[count] = Vect_new_line_struct();
+ Vect_copy_xyz_to_pnts(arrPoints[count], arrPoints2[i]->x, arrPoints2[i]->y, arrPoints2[i]->z, arrPoints2[i]->n_points);
+ count++;
+ }
+
+ side = extract_inner_contour(Points2, tPoints, &visited);
+ }
+
+ arrPoints = G_realloc(arrPoints, count*sizeof(struct line_pnts *));
+ *inner_count = count;
+ *iPoints = arrPoints;
+
+ G_free(visited.a);
+ Vect_destroy_line_struct(tPoints);
+ Vect_destroy_line_struct(sPoints);
+ Vect_destroy_line_struct(Points2);
+
return;
}
More information about the grass-commit
mailing list