[GRASS-SVN] r57769 - grass/branches/releasebranch_6_4/vector/v.label.sa

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Sep 20 18:27:55 PDT 2013


Author: hamish
Date: 2013-09-20 18:27:55 -0700 (Fri, 20 Sep 2013)
New Revision: 57769

Modified:
   grass/branches/releasebranch_6_4/vector/v.label.sa/labels.c
   grass/branches/releasebranch_6_4/vector/v.label.sa/labels.h
Log:
backport a number of bug fixes, speedups, and deal with a few compiler warnings (merge r37247, r39050, r39080, r39082, r39694, r57768 from devbr6)

Modified: grass/branches/releasebranch_6_4/vector/v.label.sa/labels.c
===================================================================
--- grass/branches/releasebranch_6_4/vector/v.label.sa/labels.c	2013-09-21 01:16:54 UTC (rev 57768)
+++ grass/branches/releasebranch_6_4/vector/v.label.sa/labels.c	2013-09-21 01:27:55 UTC (rev 57769)
@@ -5,8 +5,6 @@
 */
 #include "labels.h"
 static int label_skyline(FT_Face face, const char *charset, label_t * label);
-static struct line_pnts *box_trans_rot(BOUND_BOX * bb, label_point_t * p,
-				       double angle);
 static void label_point_candidates(label_t * label);
 static void label_line_candidates(label_t * label);
 static int candidate_compare(const void *a, const void *b);
@@ -20,6 +18,9 @@
 			       label_point_t * p);
 static int box_overlap(BOUND_BOX * a, BOUND_BOX * b);
 static int box_overlap2(struct line_pnts *a, struct line_pnts *b);
+static int segments_intersect(double x1, double y1, double x2, double y2,
+			      double x3, double y3, double x4, double y4,
+			      double *x, double *y);
 
 /**
  * The font size in map units. A global variable because I'm lazy :P
@@ -64,13 +65,13 @@
 
     label_sz = Vect_get_num_primitives(&Map, legal_types);
 
-    G_debug(1, "Need to allocate %d bytes of memory",
+    G_debug(1, "Need to allocate %lu bytes of memory",
 	    sizeof(label_t) * label_sz);
-    labels = malloc(sizeof(label_t) * label_sz);
+    labels = (label_t *) G_malloc(sizeof(label_t) * label_sz);
     G_debug(1, "labels=%p", labels);
 
     if (labels == NULL)
-	G_fatal_error(_("Cannot allocate %d bytes of memory"),
+	G_fatal_error(_("Cannot allocate %lu bytes of memory"),
 		      sizeof(label_t) * label_sz);
 
     /* open database */
@@ -126,9 +127,9 @@
 
 	if (i == label_sz) {	/* we need more memory */
 	    label_sz += 100;
-	    G_debug(1, "Need to resize %p to %d bytes of memory",
+	    G_debug(1, "Need to resize %p to %lu bytes of memory",
 		    (void *)labels, sizeof(label_t) * label_sz);
-	    labels = realloc(labels, sizeof(label_t) * label_sz);
+	    labels = G_realloc(labels, sizeof(label_t) * label_sz);
 	    if (labels == NULL) {
 		G_fatal_error(_("Cannot allocate more memory"));
 	    }
@@ -153,7 +154,7 @@
 	if (cat < 0)
 	    continue;		/* no cat for this field */
 
-	sql = G_malloc(sql_len);
+	sql = (char *) G_malloc(sql_len);
 	/* Read label from database */
 	if (p->overlap->answer[0] != '\0') {
 	    sprintf(sql, "select %s,%s from %s where %s = %d",
@@ -167,7 +168,7 @@
 	G_debug(3, "SQL: %s", sql);
 	db_init_string(&query);
 	db_set_string(&query, sql);
-	free(sql);
+	G_free(sql);
 
 	if (db_open_select_cursor(driver, &query, &cursor, DB_SEQUENTIAL) !=
 	    DB_OK)
@@ -185,13 +186,18 @@
 
 	table = db_get_cursor_table(&cursor);
 	column = db_get_table_column(table, 0);	/* first column */
+
 	db_init_string(&value);
 	db_convert_column_value_to_string(column, &value);
+
 	G_debug(3, "Label: %s", db_get_string(&value));
 
 	/* ignore empty strings */
-	if (strlen(db_get_string(&value)) == 0)
+	if (strlen(db_get_string(&value)) == 0) {
+	    Vect_destroy_cats_struct(Cats);
+	    Vect_destroy_line_struct(Points);
 	    continue;
+	}
 
 	labels[i].text = G_strdup(db_get_string(&value));
 	labels[i].cat = cat;
@@ -372,9 +378,10 @@
 
     /* generate candidate location for each label based on feture type
      * see chapter 5 of MERL-TR-96-04 */
+	G_debug(3, "n_labels=%d", n_labels);
     fprintf(stderr, "Generating label candidates: ...");
     for (i = 0; i < n_labels; i++) {
-	G_percent(i, n_labels - 1, 1);
+	G_percent(i, n_labels, 1);
 	switch (labels[i].type) {
 	case GV_POINT:
 	    G_debug(3, "Point (%d): %s", i, labels[i].text);
@@ -393,6 +400,7 @@
 	    break;
 	}
     }
+    G_percent(n_labels, n_labels, 1);
     Vect_close(&Map);
     return;
 }
@@ -407,7 +415,7 @@
     int i;
     label_candidate_t *candidates;
 
-    candidates = calloc(19, sizeof(label_candidate_t));
+    candidates = G_calloc(19, sizeof(label_candidate_t));
     if (candidates == NULL) {
 	G_fatal_error("Cannot allocate memory.");
     }
@@ -550,8 +558,8 @@
 
 	return;
     }
-    above_candidates = calloc(n, sizeof(label_candidate_t));
-    below_candidates = calloc(n, sizeof(label_candidate_t));
+    above_candidates = G_calloc(n, sizeof(label_candidate_t));
+    below_candidates = G_calloc(n, sizeof(label_candidate_t));
     if ((above_candidates == NULL) || (below_candidates == NULL)) {
 	G_fatal_error("Cannot allocate memory.");
     }
@@ -761,15 +769,15 @@
 	return;
     }
 
-    candidates = calloc(n * 2, sizeof(label_candidate_t));
+    candidates = G_calloc(n * 2, sizeof(label_candidate_t));
     for (i = 0; i < n; i++) {
 	memcpy(&candidates[i * 2], &above_candidates[i],
 	       sizeof(label_candidate_t));
 	memcpy(&candidates[i * 2 + 1], &below_candidates[i],
 	       sizeof(label_candidate_t));
     }
-    free(above_candidates);
-    free(below_candidates);
+    G_free(above_candidates);
+    G_free(below_candidates);
 
     n_c = n * 2;
     /* pick the 32 best candidates */
@@ -783,7 +791,7 @@
 	    Vect_destroy_line_struct(candidates[i].swathline);
 	}
 
-	tmp = realloc(candidates, sizeof(label_candidate_t) * 32);
+	tmp = G_realloc(candidates, sizeof(label_candidate_t) * 32);
 	if (tmp != NULL) {
 	    candidates = tmp;
 	}
@@ -836,43 +844,44 @@
     return Points;
 }
 
-/**
- * This function rotates and translates the label bounding box to the
- * given point, and returns it as a polygon.
- * @param bb The bounding box to translate and rotate.
- * @param p The point to translate the bounding box to
- * @param angle The angle (in radians) to rotate the label counter-clockwise
- * @return A lint_pnts structure containing the rotated and translated
- * bounding box as a polygon.
- */
-static struct line_pnts *box_trans_rot(BOUND_BOX * bb, label_point_t * p,
-				       double angle)
+#define SET_POINT(P, i, X, Y) (P)->x[(i)]=(X); (P)->y[(i)]=(Y); (P)->z[(i)]=0
+
+struct line_pnts *box_trans_rot(BOUND_BOX * bb, label_point_t * p,
+				double angle)
 {
     struct line_pnts *Points;
     double x0, y0, x1, y1, x2, y2;
 
     Points = Vect_new_line_struct();
+    Points->x = G_calloc(5, sizeof(double));
+    Points->y = G_calloc(5, sizeof(double));
+    Points->z = G_calloc(5, sizeof(double));
+    Points->n_points=5;
+    Points->alloc_points=5;
+    if((Points->x == NULL) || (Points->y == NULL)) {
+	return NULL;
+    }
 
     /* Lower Left, no rotation needed */
     x0 = p->x + bb->W;
     y0 = p->y + bb->S;
-    Vect_append_point(Points, x0, y0, 0);
+    SET_POINT(Points, 0, x0, y0);
     /* Lower Right */
     x1 = (bb->E - bb->W) * cos(angle);
     y1 = (bb->E - bb->W) * sin(angle);
-    Vect_append_point(Points, x0 + x1, y0 + y1, 0);
+    SET_POINT(Points, 1, x0 + x1, y0 + y1);
 
     /* Upper Right */
     x2 = (bb->N - bb->S) * sin(angle);
     y2 = (bb->N - bb->S) * cos(angle);
     /* First translate to LR, and then translate like UL */
-    Vect_append_point(Points, x0 + x1 - x2, y0 + y1 + y2, 0);
+    SET_POINT(Points, 2, x0 + x1 - x2, y0 + y1 + y2);
 
     /* Upper Left */
-    Vect_append_point(Points, x0 - x2, y0 + y2, 0);
+    SET_POINT(Points, 3, x0 - x2, y0 + y2);
 
     /* close polygon */
-    Vect_append_point(Points, x0, y0, 0);
+    SET_POINT(Points, 4, x0, y0);
 
     return Points;
 }
@@ -957,55 +966,49 @@
     for (i = 1; i < candidate->swathline->n_points; i++) {
 	int r;
 	double b, h;
-	double px1, py1, pz1, px2, py2, pz2;
+	double px, py, pz;
 
-	r = Vect_segment_intersection(x1, y1, 0, x2, y2, 0,
-				      candidate->swathline->x[i - 1],
-				      candidate->swathline->y[i - 1],
-				      0,
-				      candidate->swathline->x[i],
-				      candidate->swathline->y[i],
-				      0,
-				      &px1, &py1, &pz1, &px2, &py2, &pz2, 0);
+	r = segments_intersect(x1, y1, x2, y2,
+				candidate->swathline->x[i - 1],
+				candidate->swathline->y[i - 1],
+				candidate->swathline->x[i],
+				candidate->swathline->y[i],
+				&px, &py);
 	/* Now calculate the area between the swath and the line */
 	switch (r) {
 	case 0:		/* no intersection */
 	    dig_distance2_point_to_line(candidate->swathline->x[i],
 					candidate->swathline->y[i], 0,
 					x1, y1, 0, x2, y2, 0, 0,
-					&px1, &py1, &pz1, &h, NULL);
+					&px, &py, &pz, &h, NULL);
 	    h = (sqrt(pow(x1 - candidate->swathline->x[i - 1], 2.0) +
 		      pow(y1 - candidate->swathline->y[i - 1], 2.0)) +
 		 h) / 2.0;
-	    b = sqrt(pow(px1 - x1, 2) + pow(py1 - y1, 2));
+	    b = sqrt(pow(px - x1, 2) + pow(py - y1, 2));
 	    flatness += b * h;
-	    x1 = px1;
-	    y1 = py1;
+	    x1 = px;
+	    y1 = py;
 	    break;
 	case 1:
 	    h = sqrt(pow(x1 - candidate->swathline->x[i - 1], 2.0) +
 		     pow(y1 - candidate->swathline->y[i - 1], 2.0));
-	    b = sqrt(pow(px1 - x1, 2) + pow(py1 - y1, 2));
+	    b = sqrt(pow(px - x1, 2) + pow(py - y1, 2));
 	    flatness += b * h * 0.5;	/* the first triangle */
-	    x1 = px1;
-	    y1 = py1;
+	    x1 = px;
+	    y1 = py;
 	    dig_distance2_point_to_line(candidate->swathline->x[i],
 					candidate->swathline->y[i], 0,
 					x1, y1, 0, x2, y2, 0, 0,
-					&px1, &py1, &pz1, &h, NULL);
-	    b = sqrt(pow(px1 - x1, 2) + pow(py1 - y1, 2));
+					&px, &py, &pz, &h, NULL);
+	    b = sqrt(pow(px - x1, 2) + pow(py - y1, 2));
 	    flatness += b * h * 0.5;	/* the second triangle */
-	    x1 = px1;
-	    y1 = py1;
+	    x1 = px;
+	    y1 = py;
 	    break;
-	case 3:
-	    x1 = px2;
-	    y1 = py2;
+	case 2:
+	    x1 = px;
+	    y1 = py;
 	    break;
-	case 5:
-	    x1 = px2;
-	    y1 = py2;
-	    break;
 	default:
 	    G_fatal_error("Programming error!!\n");
 	    break;
@@ -1040,7 +1043,7 @@
      */
     trbb = box_trans_rot(&label->bb, &candidate->point, candidate->rotation);
     n = Vect_select_lines_by_polygon(&Map, trbb, 0, NULL, GV_POINT, il);
-
+    Vect_destroy_line_struct(trbb);
     pointover = (double)il->n_values;
     Vect_destroy_list(il);
 
@@ -1074,13 +1077,15 @@
     n = Vect_select_lines_by_polygon(&Map, trbb, 0, NULL, linetype, il);
 
     if (n == 0) {
+	Vect_destroy_line_struct(trbb);
+	Vect_destroy_list(il);
 	return 0.0;
     }
 
     for (i = 0; i < il->n_values; i++) {
 	int j, found = 0;
 	struct line_pnts *line;
-	label_point_t v, v1, v2;
+	label_point_t v = {0, 0}, v1 = {0, 0} , v2 = {0 ,0};
 
 	line = Vect_new_line_struct();
 	Vect_read_line(&Map, line, NULL, il->value[i]);
@@ -1090,30 +1095,23 @@
 
 	    for (k = 1; k < trbb->n_points; k++) {
 		int r;
-		double x1, x2, y1, y2, z1, z2;
+		double x=0, y=0;
 
-		r = Vect_segment_intersection(trbb->x[k - 1], trbb->y[k - 1],
-					      0, trbb->x[k], trbb->y[k], 0,
-					      line->x[j - 1], line->y[j - 1],
-					      0, line->x[j], line->y[j], 0,
-					      &x1, &y1, &z1, &x2, &y2, &z2,
-					      0);
+		r = segments_intersect(trbb->x[k - 1], trbb->y[k - 1],
+				      trbb->x[k], trbb->y[k],
+				      line->x[j - 1], line->y[j - 1],
+				      line->x[j], line->y[j],
+				      &x, &y);
 		if (r > 0) {	/* intersection at one point */
 		    if (found == 0) {
 			found = 1;
-			v1.x = x1;
-			v1.y = y1;
+			v1.x = x;
+			v1.y = y;
 		    }
 		    else {
 			found++;
-			if (r > 1) {
-			    v2.x = x2;
-			    v2.y = y2;
-			}
-			else {
-			    v2.x = x1;
-			    v2.y = y1;
-			}
+			v2.x = x;
+			v2.y = y;
 		    }
 		}
 	    }
@@ -1131,6 +1129,7 @@
 	Vect_destroy_line_struct(line);
     }
 
+    Vect_destroy_line_struct(trbb);
     Vect_destroy_list(il);
     return lineover;
 }
@@ -1237,7 +1236,7 @@
 			label_intersection_t *li;
 
 			n = ++(labels[i].candidates[j].n_intersections);
-			li = realloc(labels[i].candidates[j].intersections,
+			li = G_realloc(labels[i].candidates[j].intersections,
 				     n * sizeof(label_intersection_t));
 			if (li == NULL)
 			    G_fatal_error("\nUnable to allocate memory\n");
@@ -1250,7 +1249,7 @@
 			}
 			labels[i].candidates[j].intersections = li;
 			n = ++(labels[k].candidates[l].n_intersections);
-			li = realloc(labels[k].candidates[l].intersections,
+			li = G_realloc(labels[k].candidates[l].intersections,
 				     n * sizeof(label_intersection_t));
 			if (li == NULL)
 			    G_fatal_error("\nUnable to allocate memory\n");
@@ -1262,6 +1261,7 @@
 		}
 	    }
 	}
+	G_debug(3, "i=%d n_labels=%d", i, n_labels);
 	G_percent(i, n_labels, 1);
     }
     G_percent(n_labels, n_labels, 1);
@@ -1299,24 +1299,82 @@
  */
 static int box_overlap2(struct line_pnts *a, struct line_pnts *b)
 {
-    int i, r = 0;
-
+    int i;
     for (i = 0; i < (a->n_points - 1); i++) {
 	int j;
-
 	for (j = 0; j < (b->n_points - 1); j++) {
-	    double d[6];
+	    int r;
+	    r = segments_intersect(a->x[i], a->y[i],
+				   a->x[i + 1], a->y[i + 1],
+				   b->x[j], b->y[j],
+				   b->x[j + 1], a->y[j + 1],
+				   NULL, NULL);
+	    if (r == 1) {
+		return 1;
+	    }
+	}
+    }
+    return 0;
+}
 
-	    r += Vect_segment_intersection(a->x[i], a->y[i], 0,
-					   a->x[i + 1], a->y[i + 1], 0,
-					   b->x[j], b->y[j], 0,
-					   b->x[j + 1], a->y[j + 1], 0,
-					   &d[0], &d[1], &d[2],
-					   &d[3], &d[4], &d[5], 0);
+/**
+ * This function checks if two line segments intersect. This function is based
+ * on the theory provided by Paul Burk.
+ * @sa http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
+ * @param x1 The X-coordinate of P1
+ * @param y1 The Y-coordinate of P1
+ * @param x2 The X-coordinate of P2
+ * @param y2 The Y-coordinate of P2
+ * @param x3 The X-coordinate of P3
+ * @param y3 The Y-coordinate of P3
+ * @param x4 The X-coordinate of P4
+ * @param y4 The Y-coordinate of P4
+ * @param x A pointer to a double which will be set to the X-coordinate of the
+            unique intersection point (Coincident segments: x4).
+ * @param y A pointer to a double which will be set to the Y-coordinate of the
+            unique intersection point (Coincident segments: y4).
+ * @return 0: No intersection. 1: Intersect. 2: The segments are coincident.
+ */
+static int segments_intersect(double x1, double y1, double x2, double y2,
+			      double x3, double y3, double x4, double y4,
+			      double *x, double *y)
+{
+    double u1numer = (x4-x3)*(y1-y3) - (y4-y3)*(x1-x3);
+    double u2numer = (x2-x1)*(y1-y3) - (y2-y1)*(x1-x3);
+    double denomin = (y4-y3)*(x2-x1) - (x4-x3)*(y2-y1);
+    double ua, ub;
+    int ret = 0;
+ /*
+    * If the denominator and numerator for the equations for ua and ub are 0 then the two lines are coincident.
+ */
+ if(((u1numer < GRASS_EPSILON) && (u1numer > -GRASS_EPSILON)) &&
+    ((u2numer < GRASS_EPSILON) && (u2numer > -GRASS_EPSILON)))
+    {
+	if((x != NULL) && (y != NULL)) {
+	    *x = x4;
+	    *y = y4;
 	}
+	ret = 2;
     }
-    if (r > 1)
-	return 1;
-    else
-	return 0;
+/*
+    * The denominators for the equations for ua and ub are the same.
+    * If the denominator for the equations for ua and ub is 0 then the two lines are parallel.
+ */
+    if((denomin < GRASS_EPSILON) && (denomin > -GRASS_EPSILON)) {
+	ret = 0; /* parallel but don't overlap */
+    }
+ /*
+    * The equations apply to lines, if the intersection of line segments is required then it is only necessary to test if ua and ub lie between 0 and 1. Whichever one lies within that range then the corresponding line segment contains the intersection point. If both lie within the range of 0 to 1 then the intersection point is within both line segments. 
+    */
+    ua = u1numer / denomin;
+    ub = u2numer / denomin;
+    if(((ua > 0.0) && (ua < 1.0)) && ((ub > 0.0) && (ub < 1.0))) {
+	ret = 1;
+	if((x != NULL) && (y != NULL)) {
+	    *x = x1 + ua * (x2 - x1);
+	    *y = y1 + ua * (y2 - y1);
+	}
+    }
+    return ret;
 }
+

Modified: grass/branches/releasebranch_6_4/vector/v.label.sa/labels.h
===================================================================
--- grass/branches/releasebranch_6_4/vector/v.label.sa/labels.h	2013-09-21 01:16:54 UTC (rev 57768)
+++ grass/branches/releasebranch_6_4/vector/v.label.sa/labels.h	2013-09-21 01:27:55 UTC (rev 57769)
@@ -184,6 +184,18 @@
 struct line_pnts *skyline_trans_rot(struct line_pnts *skyline,
 				    label_point_t * p, double angle);
 
+/**
+ * This function rotates and translates the label bounding box to the
+ * given point, and returns it as a polygon.
+ * @param bb The bounding box to translate and rotate.
+ * @param p The point to translate the bounding box to
+ * @param angle The angle (in radians) to rotate the label counter-clockwise
+ * @return A lint_pnts structure containing the rotated and translated
+ * bounding box as a polygon.
+ */
+struct line_pnts *box_trans_rot(BOUND_BOX * bb, label_point_t * p,
+				double angle);
+
 void free_freetypecap(struct GFONT_CAP *ftcap);
 struct GFONT_CAP *find_font_from_freetypecap(const char *font);
 



More information about the grass-commit mailing list