[GRASS-SVN] r31127 - grass/trunk/vector/v.label.sa

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Apr 26 17:54:53 EDT 2008


Author: wolf
Date: 2008-04-26 17:54:53 -0400 (Sat, 26 Apr 2008)
New Revision: 31127

Modified:
   grass/trunk/vector/v.label.sa/labels.c
   grass/trunk/vector/v.label.sa/main.c
Log:
Fixed label placement, LineOver, label box creation, line candidate sorting and selection, Flatness and PointOver

Modified: grass/trunk/vector/v.label.sa/labels.c
===================================================================
--- grass/trunk/vector/v.label.sa/labels.c	2008-04-26 07:26:04 UTC (rev 31126)
+++ grass/trunk/vector/v.label.sa/labels.c	2008-04-26 21:54:53 UTC (rev 31127)
@@ -101,7 +101,7 @@
     buffer = atof(p->isize->answer);
 
     /* use 1 point = 1 map unit */
-    if (FT_Set_Char_Size(face, (int)(font_size * 64.0), 0, 100, 100))
+    if (FT_Set_Char_Size(face, (int)((font_size*0.95) * 64.0), 0, 100, 100))
 	G_fatal_error(_("Unable to set font size"));
 
     /* start reading the map */
@@ -331,7 +331,7 @@
 	G_percent(i, n_labels - 1, 1);
 	switch (labels[i].type) {
 	case GV_POINT:
-	    G_debug(1, "Line (%d): %s", i, labels[i].text);
+	    G_debug(3, "Line (%d): %s", i, labels[i].text);
 	    label_point_candidates(&labels[i]);
 	    break;
 	case GV_LINE:
@@ -456,7 +456,7 @@
 	candidates[i].score += 10.0 * label_pointover(label, &candidates[i]);
 	candidates[i].score += 15.0 * label_lineover(label, &candidates[i],
 						     GV_LINE);
-	G_debug(1, "calling label_lineover('%s', %d)", label->text, i);
+	G_debug(5, "calling label_lineover('%s', %d)", label->text, i);
 	candidates[i].score += 10.0 * label_lineover(label, &candidates[i],
 						     GV_BOUNDARY);
 	candidates[i].rotation = 0;
@@ -529,6 +529,7 @@
 		pos, i, p1.x, p1.y, p2.x, p2.y);
 
 	angle = atan2((p2.y - p1.y), (p2.x - p1.x));
+	
 	if ((angle > M_PI / 2) || (angle < -M_PI / 2)) {
 	    /* turn label around 180 degrees if it would be upside down */
 	    double tmp;
@@ -540,8 +541,6 @@
 	    p1.y = p2.y;
 	    p2.y = tmp;
 
-	    /*                              p1.x = p1.x + length * cos(angle);
-	     * p1.x = p1.x + length * sin(angle); */
 	    if (angle < 0)
 		angle += M_PI;
 	    else
@@ -601,16 +600,16 @@
 	    below_distance = height - label->bb.S;
 	}
 
-	/* place a skyline at 1.1 * above_distance above line, and
-	 * 1.1 * below_distance + height below line */
+	/* place a skyline at above_distance above line, and
+	 * below_distance + height below line */
 	{
 	    label_point_t tp;
 
-	    tp.x = p1.x - 1.1 * above_distance * sin(angle);
-	    tp.y = p1.y + 1.1 * above_distance * cos(angle);
+	    tp.x = p1.x - above_distance * sin(angle);
+	    tp.y = p1.y + above_distance * cos(angle);
 	    above_skyline = skyline_trans_rot(label->skyline, &tp, angle);
-	    tp.x = p1.x + (1.1 * below_distance + height) * sin(angle);
-	    tp.y = p1.y - (1.1 * below_distance + height) * cos(angle);
+	    tp.x = p1.x + (below_distance + height) * sin(angle);
+	    tp.y = p1.y - (below_distance + height) * cos(angle);
 	    below_skyline = skyline_trans_rot(label->skyline, &tp, angle);
 	}
 	/* find minimum distance between swath line and skylines */
@@ -620,10 +619,9 @@
 	minimum_below_distance = min_dist_2_lines(below_skyline,
 						  below_candidates[i].swathline,
 						  &minimum_below_distance_p);
-
+	
 	/* adjust skylines so that the minimum distance is equal to the ideal
 	 * distance (= 0.3 * glyph height of capital X) */
-
 	above_distance += ideal_distance - minimum_above_distance;
 	below_distance += ideal_distance - minimum_below_distance;
 
@@ -647,13 +645,16 @@
 	above_candidates[i].rotation = angle;
 	below_candidates[i].rotation = angle;
 
+	above_candidates[i].score = 0.0;
+	below_candidates[i].score = 0.0;
 	/* AveDist */
 	above_candidates[i].score += label_avedist(label, &above_candidates[i]);
 	below_candidates[i].score += label_avedist(label, &below_candidates[i]);
-
+	
 	/* flatness */
 	flatness = label_flatness(label, &above_candidates[i]);
 	above_candidates[i].score += flatness;
+	flatness = label_flatness(label, &below_candidates[i]);
 	below_candidates[i].score += flatness;
 
 	/* centerdness */
@@ -671,16 +672,10 @@
 	above_candidates[i].lineover = 15.0 *
 	    label_lineover(label, &above_candidates[i], GV_LINE);
 	above_candidates[i].score += above_candidates[i].lineover;
-if(label->cat == 1) {
-	printf("%s: above candidate %d: lineover=%lf score=%lf\n",label->text, i, above_candidates[i].lineover, above_candidates[i].score);
-}
 
 	below_candidates[i].lineover = 15.0 *
 	    label_lineover(label, &below_candidates[i], GV_LINE);
 	below_candidates[i].score += below_candidates[i].lineover;
-if(label->cat == 1) {
-	printf("%s: below candidate %d: lineover=%lf score=%lf\n",label->text, i, below_candidates[i].lineover, below_candidates[i].score);
-}
 
 	/* AreaOver */
 	above_candidates[i].score += 10.0 *
@@ -689,11 +684,12 @@
 	    label_lineover(label, &below_candidates[i], GV_BOUNDARY);
 
 	/* aboveness */
-	below_candidates[i].score += 0.25;
+	below_candidates[i].score += 1.25;
 
 	i++;
     }
     n = i;
+    
     if (n == 0) {
 	/* treat the line as a point feature */
 	struct line_pnts *tmp, *tmp_shape;
@@ -712,47 +708,33 @@
 	return;
     }
 
+    candidates = 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);
+
+    n_c = n*2;
     /* pick the 32 best candidates */
-    qsort(above_candidates, n, sizeof(label_candidate_t), candidate_compare);
-    qsort(below_candidates, n, sizeof(label_candidate_t), candidate_compare);
+    qsort(candidates, n_c, sizeof(label_candidate_t), candidate_compare);
 
-    if (n > 32)
-	n_c = 32;
-    else
-	n_c = n;
-
-    candidates = calloc(n_c, sizeof(label_candidate_t));
-    for (i = 0; i < n_c; i++) {
-	if (candidate_compare(&below_candidates[i], &above_candidates[i]) < 0) {
-	    memcpy(&candidates[i], &below_candidates[i],
-		   sizeof(label_candidate_t));
-	    memset(&below_candidates[i], 0, sizeof(label_candidate_t));
+    if(n_c > 32) {
+	label_candidate_t *tmp;
+	for (i=32; i < n; i++) {
+	    Vect_destroy_line_struct(candidates[i].baseline);
+	    Vect_destroy_line_struct(candidates[i].swathline);
 	}
-	else {
-	    memcpy(&candidates[i], &above_candidates[i],
-		   sizeof(label_candidate_t));
-	    memset(&above_candidates[i], 0, sizeof(label_candidate_t));
+	
+	tmp = realloc(candidates, sizeof(label_candidate_t)*32);
+	if(tmp != NULL) {
+	    candidates = tmp;
 	}
-
-	if (candidates[i].above) {
-	    Vect_destroy_line_struct(below_candidates[i].baseline);
-	    Vect_destroy_line_struct(below_candidates[i].swathline);
-	}
-	else {
-	    Vect_destroy_line_struct(above_candidates[i].baseline);
-	    Vect_destroy_line_struct(above_candidates[i].swathline);
-	}
+	n_c = 32;
     }
-
-    for (; i < n; i++) {
-	Vect_destroy_line_struct(above_candidates[i].baseline);
-	Vect_destroy_line_struct(above_candidates[i].swathline);
-	Vect_destroy_line_struct(below_candidates[i].baseline);
-	Vect_destroy_line_struct(below_candidates[i].swathline);
-    }
-    free(above_candidates);
-    free(below_candidates);
-
     label->current_candidate =
 	(int)((double)(n_c) * (rand() / (RAND_MAX + 1.0)));
     label->candidates = candidates;
@@ -812,27 +794,30 @@
 				       double angle)
 {
     struct line_pnts *Points;
-    double x0, y0, x, y;
+    double x0, y0, x1, y1, x2, y2;
 
     Points = Vect_new_line_struct();
 
-    x0 = bb->W * cos(angle) - bb->N * sin(angle);
-    y0 = bb->W * sin(angle) + bb->E * cos(angle);
-    Vect_append_point(Points, x0 + p->x, y0 + p->y, 0);
+    /* Lower Left, no rotation needed */
+    x0 = p->x + bb->W;
+    y0 = p->y + bb->S;
+    Vect_append_point(Points, x0, y0, 0);
+    /* 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);
 
-    x = bb->E * cos(angle) - bb->N * sin(angle);
-    y = bb->E * sin(angle) + bb->N * cos(angle);
-    Vect_append_point(Points, x + p->x, y + p->y, 0);
+    /* 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);
 
-    x = bb->E * cos(angle) - bb->S * sin(angle);
-    y = bb->E * sin(angle) + bb->S * cos(angle);
-    Vect_append_point(Points, x + p->x, y + p->y, 0);
+    /* Upper Left */
+    Vect_append_point(Points, x0 - x2, y0 + y2, 0);
 
-    x = bb->W * cos(angle) - bb->S * sin(angle);
-    y = bb->W * sin(angle) + bb->S * cos(angle);
-    Vect_append_point(Points, x + p->x, y + p->y, 0);
-    // close line;
-    Vect_append_point(Points, x0 + p->x, y0 + p->y, 0);
+    /* close polygon */
+    Vect_append_point(Points, x0, y0, 0);
 
     return Points;
 }
@@ -888,14 +873,22 @@
     double flatness = 0.0, x0, y0, x1, y1, x2, y2;
     int i;
 
-/* first generate a line which is parallel to the baseline, 
-   but the ideal distance away from it.*/
+    /* first generate a line which is parallel to the baseline, 
+     but the ideal distance away from it, and is between the label and the
+     base line */
     line = Vect_new_line_struct();
-    x0 = x1 = candidate->point.x + ideal_distance * cos(candidate->rotation);
-    y0 = y1 = candidate->point.y - ideal_distance * sin(candidate->rotation);
+    if(candidate->above) {
+	x0 = x1 = candidate->point.x + ideal_distance * sin(candidate->rotation);
+	y0 = y1 = candidate->point.y - ideal_distance * cos(candidate->rotation);
+    }
+    else {
+	x0 = x1 = candidate->point.x - ideal_distance * sin(candidate->rotation);
+	y0 = y1 = candidate->point.y + ideal_distance * cos(candidate->rotation);
+    }
+
     Vect_append_point(line, x1, y1, 0);
-    x2 = x1 + (label->bb.E - label->bb.W) * cos(candidate->rotation);
-    y2 = y1 + (label->bb.E - label->bb.W) * sin(candidate->rotation);
+    x2 = x1 + (label->bb.E - label->bb.W) * sin(candidate->rotation);
+    y2 = y1 + (label->bb.E - label->bb.W) * cos(candidate->rotation);
     Vect_append_point(line, x2, y2, 0);
 
     /* now calculate the are between candidate->swathline and line */
@@ -973,22 +966,17 @@
 {
     double pointover;
     struct ilist *il;
-    struct line_pnts *trsk;
-    BOUND_BOX bb;
-
+    struct line_pnts *trbb;
+    int n;
+    
     il = Vect_new_list();
 
-    trsk = skyline_trans_rot(label->skyline, &candidate->point,
+/*    trsk = skyline_trans_rot(label->skyline, &candidate->point,
 			     candidate->rotation);
+*/
+    trbb = box_trans_rot(&label->bb, &candidate->point, candidate->rotation);
+    n = Vect_select_lines_by_polygon(&Map, trbb, 0, NULL, GV_POINT, il);
 
-    bb.N = label->bb.N + candidate->point.y + buffer;
-    bb.E = label->bb.E + candidate->point.x + buffer;
-    bb.W = label->bb.W + candidate->point.x - buffer;
-    bb.S = label->bb.S + candidate->point.y - buffer;
-    bb.T = label->bb.T;
-    bb.B = label->bb.B;
-    Vect_select_lines_by_box(&Map, &bb, GV_POINT, il);
-
     pointover = (double)il->n_values;
     Vect_destroy_list(il);
 
@@ -1006,26 +994,25 @@
 {
     double lineover = 0.0;
     struct ilist *il;
-    struct line_pnts *trsk, *trbb;
+    struct line_pnts *trbb;
     label_point_t b;
     int i, n;
 
     il = Vect_new_list();
-    G_debug(3, "Candidate point is: (%lf,%lf)",
+    G_debug(5, "Candidate point is: (%lf,%lf)",
 	    candidate->point.x, candidate->point.y);
-    trsk = skyline_trans_rot(label->skyline, &candidate->point,
-			     candidate->rotation);
-    b.x = (label->bb.E - label->bb.W) * cos(candidate->rotation);
-    b.y = (label->bb.E - label->bb.W) * sin(candidate->rotation);
+/*    trsk = skyline_trans_rot(label->skyline, &candidate->point,
+			     candidate->rotation);*/
+    b.x = abs((label->bb.E - label->bb.W) * cos(candidate->rotation));
+    b.y = abs((label->bb.E - label->bb.W) * sin(candidate->rotation));
 
     trbb = box_trans_rot(&label->bb, &candidate->point, candidate->rotation);
     n = Vect_select_lines_by_polygon(&Map, trbb, 0, NULL, linetype, il);
-
+    
     if(n == 0) {
 	return 0.0;
     }
 
-
     for (i = 0; i < il->n_values; i++) {
 	int j, found=0;
 	struct line_pnts *line;
@@ -1045,8 +1032,8 @@
 					      line->x[j],line->y[j],0,
 					      &x1, &y1, &z1, &x2, &y2, &z2, 0);
 		if (r > 0) { /* intersection at one point */
-		    if (!found) {
-			found++;
+		    if (found==0) {
+			found=1;
 			v1.x = x1;
 			v1.y = y1;
 		    }
@@ -1064,10 +1051,14 @@
 		}
 	    }
 	}
-	v.x = v2.x - v1.x;
-	v.y = v2.y - v1.y;
-	lineover += 1.0 + 9.0 * fabs(v.x * b.x + v.y * b.y)
-		/ (sqrt(v.x * v.x + v.y * v.y) * sqrt(b.x * b.x + b.y * b.y));
+	if(found > 1) {
+	    double cosvb;
+	    v.x = abs(v2.x - v1.x);
+	    v.y = abs(v2.y - v1.y);
+	    cosvb = ((b.x*v.x+b.y*v.y) /
+		     (sqrt(b.x*b.x+b.y*b.y)*sqrt(v.x*v.x+v.y*v.y)));
+	    lineover += 1.0 + 9.0 * cosvb;
+	}
     }
 
     Vect_destroy_list(il);

Modified: grass/trunk/vector/v.label.sa/main.c
===================================================================
--- grass/trunk/vector/v.label.sa/main.c	2008-04-26 07:26:04 UTC (rev 31126)
+++ grass/trunk/vector/v.label.sa/main.c	2008-04-26 21:54:53 UTC (rev 31127)
@@ -71,32 +71,44 @@
 
 /* dumping the skyline of the labels */
 /*    {
+	int n=1;
 	char *f;
 	FILE *skyf;
 	f = G_tempfile();
 	skyf = fopen(f, "w");
-	printf("Writing label skylines to file %s", f);
+	printf("Writing label skylines & label points to file %s", f);
 	fprintf(skyf, "VERTI:\n");
+	printf("\n%d labels:\n", n_labels);
 	for (i = 0; i < n_labels; i++) {
-	    int j;
+	    printf("%s has %d candidates\n", labels[i].text, labels[i].n_candidates);
 	    if (labels[i].n_candidates > 0) {
+		int j;
 		label_t *l = &labels[i];
-		label_candidate_t *cc = &l->candidates[l->current_candidate];
-		struct line_pnts *sky = skyline_trans_rot(l->skyline,
-							  &cc->point,
-							  cc->rotation);
-		fprintf(skyf, "L %d 1\n", sky->n_points);
-		for(j=0;j < sky->n_points; j++) {
-		    fprintf(skyf, " %.12f %.12f\n", sky->x[j], sky->y[j]);
+		j = l->current_candidate;
+//		for(j=0; j < l->n_candidates; j++) {
+		{
+		    int k;
+		    label_candidate_t *cc = &l->candidates[j];
+		    struct line_pnts *sky = skyline_trans_rot(l->skyline,
+							      &cc->point,
+							      cc->rotation);
+		    fprintf(skyf, "L %d 1\n", sky->n_points);
+		    for(k=0;k < sky->n_points; k++) {
+			fprintf(skyf, " %.12f %.12f\n", sky->x[k], sky->y[k]);
+		    }
+		    fprintf(skyf, " %-5d %-10d\n", 1, 1000+n);
+		    // The label point
+		    fprintf(skyf, "P 1 1\n");
+		    fprintf(skyf, " %.12f %.12f\n", cc->point.x, cc->point.y);
+		    fprintf(skyf, " %-5d %-10d\n", 1, 2000+n);
+		    n++;
 		}
-		fprintf(skyf, " %-5d %-10d\n", 1, i+1);
 	    }
-	    G_percent(i, (n_labels - 1), 1);
     	}
 	free(f);
     	fclose(skyf);
-    }
-*/
+    }*/
+
     return EXIT_SUCCESS;
 }
 
@@ -228,7 +240,7 @@
     fprintf(labelf, "north: %lf\n", label->candidates[cc].point.y);
     fprintf(labelf, "xoffset: %lf\n", 0.0); // * (size));
     fprintf(labelf, "yoffset: %lf\n", 0.0); // * (size));
-    fprintf(labelf, "ref: %s\n", "center left");
+    fprintf(labelf, "ref: %s\n", "bottom left");
 
     fprintf(labelf, "font: %s\n", p->font->answer);
     fprintf(labelf, "color: %s\n", p->color->answer);



More information about the grass-commit mailing list