/* one new saddle face with 4 edges */ void newsad (struct surface *this_srf, struct arc *arc1, struct arc *arc2, struct circle *circle1, struct circle *circle2, struct torus *torus_ptr, double wrap_angle) { struct vertex *vertex1, *vertex2, *vertex3, *vertex4; struct arc *arc3, *arc4; struct face *saddle_fac; struct sphere *atom1, *atom2; atom1 = circle1 -> atm; atom2 = circle2 -> atm; /* gather vertices */ vertex1 = arc1 -> vtx[0]; vertex2 = arc1 -> vtx[1]; vertex3 = arc2 -> vtx[0]; vertex4 = arc2 -> vtx[1]; /* set up arcs */ arc3 = new_arc (circle2, vertex2, vertex3, CONVEX, 0, (double) 0.0, 0L, 0L, 0L); if (error()) return; this_srf -> n_arc++; arc4 = new_arc (circle1, vertex4, vertex1, CONVEX, 0, (double) 0.0, 0L, 0L, 0L); if (error()) return; this_srf -> n_arc++; arc3 -> phi = wrap_angle; arc4 -> phi = wrap_angle; /* add convex arcs to atom list */ arc3 -> next = atom2 -> first_arc; atom2 -> first_arc = arc3; arc4 -> next = atom1 -> first_arc; atom1 -> first_arc = arc4; /* set up saddle face */ saddle_fac = new_face (NULL, SADDLE); if (error()) return; saddle_fac -> ptr.tor = torus_ptr; link_face (this_srf, saddle_fac); if (error()) return; add2face (saddle_fac, arc1, arc3, arc2, arc4); if (error()) return; }
/* free (no collision) torus saddle surface */ void free_saddle (struct surface *this_srf, struct torus *torus_ptr) { struct face *saddle_fac; struct circle *circle1, *circle2; struct arc *arc1, *arc2; struct sphere *atom1, *atom2; atom1 = (torus_ptr -> atm[0]); atom2 = (torus_ptr -> atm[1]); /* set up circles */ circle1 = new_contact_circle (this_srf, torus_ptr, 0); if (error()) return; circle2 = new_contact_circle (this_srf, torus_ptr, 1); if (error()) return; /* set up arcs */ arc1 = new_arc (circle2, NULL, NULL, CONVEX, 0, (double) 0.0, 0L, 0L, 0L); if (error()) return; this_srf -> n_arc++; arc2 = new_arc (circle1, NULL, NULL, CONVEX, 0, (double) 0.0, 0L, 0L, 0L); if (error()) return; this_srf -> n_arc++; arc1 -> phi = 2 * PI; arc2 -> phi = 2 * PI; /* add convex arcs to atom list */ arc1 -> next = atom2 -> first_arc; atom2 -> first_arc = arc1; arc2 -> next = atom1 -> first_arc; atom1 -> first_arc = arc2; /* allocate saddle face */ saddle_fac = new_face (NULL, SADDLE); if (error()) return; saddle_fac -> ptr.tor = torus_ptr; link_face (this_srf, saddle_fac); if (error()) return; add2face (saddle_fac, arc1, arc2, NULL, NULL); if (error()) return; }
/* * Read symbol specified by name. * Name: group/name | group/name@mapset * (later add syntax to prefer symbol from GISBASE) * S_read() searches first in mapsets (standard GRASS search) and * then in GISBASE/etc/symbol/ */ SYMBOL *S_read(const char *sname) { int i, j, k, l; FILE *fp; char group[500], name[500], buf[2001]; const char *ms; char *c; double x, y, x2, y2, rad, ang1, ang2; int r, g, b; double fr, fg, fb; int ret; char clock; SYMBOL *symb; int current; /* current part_type */ SYMBPART *part; /* current part */ SYMBCHAIN *chain; /* current chain */ SYMBEL *elem; /* current element */ G_debug(3, "S_read(): sname = %s", sname); /* Find file */ /* Get group and name */ strcpy(group, sname); c = strchr(group, '/'); if (c == NULL) { G_warning(_("Incorrect symbol name: '%s' (should be: group/name or group/name@mapset)"), sname); return NULL; } c[0] = '\0'; c++; strcpy(name, c); G_debug(3, " group: '%s' name: '%s'", group, name); /* Search in mapsets */ sprintf(buf, "symbol/%s", group); ms = G_find_file(buf, name, NULL); if (ms != NULL) { /* Found in mapsets */ fp = G_fopen_old(buf, name, ms); } else { /* Search in GISBASE */ sprintf(buf, "%s/etc/symbol/%s", G_gisbase(), sname); fp = fopen(buf, "r"); } if (fp == NULL) { G_warning(_("Cannot find/open symbol: '%s'"), sname); return NULL; } /* create new symbol */ symb = new_symbol(); current = OBJ_NONE; /* no part */ /* read file */ while (G_getl2(buf, 2000, fp) != 0) { G_chop(buf); G_debug(3, " BUF: [%s]", buf); /* skip empty and comment lines */ if ((buf[0] == '#') || (buf[0] == '\0')) continue; get_key_data(buf); if (strcmp(key, "VERSION") == 0) { if (strcmp(data, "1.0") != 0) { sprintf(buf, "Wrong symbol version: '%s'", data); return (err(fp, symb, buf)); } } else if (strcmp(key, "BOX") == 0) { if (sscanf(data, "%lf %lf %lf %lf", &x, &y, &x2, &y2) != 4) { sprintf(buf, "Incorrect box definition: '%s'", data); return (err(fp, symb, buf)); } symb->xscale = 1 / (x2 - x); symb->yscale = 1 / (y2 - y); if (x2 - x > y2 - y) { symb->scale = symb->xscale; } else { symb->scale = symb->yscale; } } else if (strcmp(key, "STRING") == 0) { G_debug(4, " STRING >"); current = OBJ_STRING; part = new_part(S_STRING); add_part(symb, part); chain = new_chain(); add_chain(part, chain); } else if (strcmp(key, "POLYGON") == 0) { G_debug(4, " POLYGON >"); current = OBJ_POLYGON; part = new_part(S_POLYGON); add_part(symb, part); } else if (strcmp(key, "RING") == 0) { G_debug(4, " RING >"); current = OBJ_RING; chain = new_chain(); add_chain(part, chain); } else if (strcmp(key, "LINE") == 0) { G_debug(4, " LINE >"); elem = new_line(); add_element(chain, elem); read_coor(fp, elem); } else if (strcmp(key, "ARC") == 0) { G_debug(4, " ARC"); ret = sscanf(data, "%lf %lf %lf %lf %lf %c", &x, &y, &rad, &ang1, &ang2, &clock); if (ret < 5) { sprintf(buf, "Incorrect arc definition: '%s'", buf); return (err(fp, symb, buf)); } if (ret == 6 && (clock == 'c' || clock == 'C')) i = 1; else i = 0; elem = new_arc(x, y, rad, ang1, ang2, i); add_element(chain, elem); } else if (strcmp(key, "END") == 0) { switch (current) { case OBJ_STRING: G_debug(4, " STRING END"); current = OBJ_NONE; break; case OBJ_POLYGON: G_debug(4, " POLYGON END"); current = OBJ_NONE; break; case OBJ_RING: G_debug(4, " RING END"); current = OBJ_POLYGON; break; } } else if (strcmp(key, "COLOR") == 0) { if (G_strcasecmp(data, "NONE") == 0) { part->color.color = S_COL_NONE; } else if (sscanf(data, "%d %d %d", &r, &g, &b) == 3) { if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) G_warning(_("Incorrect symbol color: '%s', using default."), buf); else { fr = r / 255.0; fg = g / 255.0; fb = b / 255.0; part->color.color = S_COL_DEFINED; part->color.r = r; part->color.g = g; part->color.b = b; part->color.fr = fr; part->color.fg = fg; part->color.fb = fb; G_debug(4, " color [%d %d %d] = [%.3f %.3f %.3f]", r, g, b, fr, fg, fb); } } else { G_warning(_("Incorrect symbol color: '%s', using default."), buf); } } else if (strcmp(key, "FCOLOR") == 0) { if (G_strcasecmp(data, "NONE") == 0) { part->fcolor.color = S_COL_NONE; } else if (sscanf(data, "%d %d %d", &r, &g, &b) == 3) { if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) G_warning(_("Incorrect symbol color: '%s', using default."), buf); else { fr = r / 255.0; fg = g / 255.0; fb = b / 255.0; part->fcolor.color = S_COL_DEFINED; part->fcolor.r = r; part->fcolor.g = g; part->fcolor.b = b; part->fcolor.fr = fr; part->fcolor.fg = fg; part->fcolor.fb = fb; G_debug(4, " color [%d %d %d] = [%.3f %.3f %.3f]", r, g, b, fr, fg, fb); } } else { G_warning(_("Incorrect symbol color: '%s', using default."), buf); } } else { sprintf(buf, "Unknown keyword in symbol: '%s'", buf); return (err(fp, symb, buf)); break; } } /* Debug output */ G_debug(3, "Number of parts: %d", symb->count); for (i = 0; i < symb->count; i++) { part = symb->part[i]; G_debug(4, " Part %d: type: %d number of chains: %d", i, part->type, part->count); G_debug(4, " color: %d: fcolor: %d", part->color.color, part->fcolor.color); for (j = 0; j < part->count; j++) { chain = part->chain[j]; G_debug(4, " Chain %d: number of elements: %d", j, chain->count); for (k = 0; k < chain->count; k++) { elem = chain->elem[k]; G_debug(4, " Element %d: type: %d", k, elem->type); if (elem->type == S_LINE) { G_debug(4, " Number of points %d", elem->coor.line.count); for (l = 0; l < elem->coor.line.count; l++) { G_debug(4, " x, y: %f %f", elem->coor.line.x[l], elem->coor.line.y[l]); } } else { G_debug(4, " arc r = %f", elem->coor.arc.r); } } } } fclose(fp); return symb; }
/* new concave face */ void new_concave_face (struct surface *this_srf, struct probe *prb) { int k; double probe_center[3]; double vertex1_coor[3], vertex2_coor[3], vertex3_coor[3], vertex4_coor[3]; double circle1_axis[3], circle2_axis[3], circle3_axis[3], circle4_axis[3]; struct circle *circle1, *circle2, *circle3, *circle4; struct vertex *vertex1, *vertex2, *vertex3, *vertex4; struct arc *arc1, *arc2, *arc3, *arc4; struct sphere *atom1, *atom2, *atom3, *atom4; struct face *concave_fac; struct pair *torus1, *torus2, *torus3, *torus4; double dot1, dot2, dot3, dot4; char message[MAX_STRING]; struct cept *ex; if (prb -> natom > 3) { sprintf (message, "%8ld probe square concave face", prb -> number); informd (message); } else { sprintf (message, "%8ld probe triangular concave face", prb -> number); informd2 (message); } atom1 = prb -> atm[0]; atom2 = prb -> atm[1]; atom3 = prb -> atm[2]; atom4 = prb -> atm[3]; torus1 = prb -> pairs[0]; torus2 = prb -> pairs[1]; torus3 = prb -> pairs[2]; torus4 = prb -> pairs[3]; for (k = 0; k < 3; k++) probe_center[k] = prb -> center[k]; /* compute vertex coordinates */ for (k = 0; k < 3; k++) { vertex1_coor[k] = (atom1 -> radius * probe_center[k] + this_srf -> probe_radius * atom1 -> center[k]) / (atom1 -> radius + this_srf -> probe_radius); vertex2_coor[k] = (atom2 -> radius * probe_center[k] + this_srf -> probe_radius * atom2 -> center[k]) / (atom2 -> radius + this_srf -> probe_radius); vertex3_coor[k] = (atom3 -> radius * probe_center[k] + this_srf -> probe_radius * atom3 -> center[k]) / (atom3 -> radius + this_srf -> probe_radius); if (atom4 != NULL) { vertex4_coor[k] = (atom4 -> radius * probe_center[k] + this_srf -> probe_radius * atom4 -> center[k]) / (atom4 -> radius + this_srf -> probe_radius); } } /* set up vertices */ vertex1 = new_vertex (vertex1_coor, (struct sphere *) atom1, prb, NULL, NULL); if (vertex1 == NULL) return; link_vertex (this_srf, vertex1); vertex2 = new_vertex (vertex2_coor, (struct sphere *) atom2, prb, NULL, NULL); if (vertex2 == NULL) return; link_vertex (this_srf, vertex2); vertex3 = new_vertex (vertex3_coor, (struct sphere *) atom3, prb, NULL, NULL); if (vertex3 == NULL) return; link_vertex (this_srf, vertex3); if (atom4 != NULL) { vertex4 = new_vertex (vertex4_coor, (struct sphere *) atom4, prb, NULL, NULL); if (vertex4 == NULL) return; link_vertex (this_srf, vertex4); } else vertex4 = NULL; /* calculate axes and set up circles */ setup_axis (probe_center, prb -> atm[0] -> center, prb -> atm[1] -> center, circle1_axis); setup_axis (probe_center, prb -> atm[1] -> center, prb -> atm[2] -> center, circle2_axis); if (atom4 == NULL) { setup_axis (probe_center, prb -> atm[2] -> center, prb -> atm[0] -> center, circle3_axis); } else if (atom4 != NULL) { setup_axis (probe_center, prb -> atm[2] -> center, prb -> atm[3] -> center, circle3_axis); setup_axis (probe_center, prb -> atm[3] -> center, prb -> atm[0] -> center, circle4_axis); } circle1 = new_circle (probe_center, this_srf -> probe_radius, circle1_axis); if (circle1 == NULL) return; link_circle (this_srf, circle1); circle1 -> theta = 0.0; circle1 -> subtype = GREAT_SUBTYPE; circle2 = new_circle (probe_center, this_srf -> probe_radius, circle2_axis); if (circle2 == NULL) return; link_circle (this_srf, circle2); circle2 -> theta = 0.0; circle2 -> subtype = GREAT_SUBTYPE; circle3 = new_circle (probe_center, this_srf -> probe_radius, circle3_axis); if (circle3 == NULL) return; link_circle (this_srf, circle3); circle3 -> theta = 0.0; circle3 -> subtype = GREAT_SUBTYPE; if (atom4 != NULL) { circle4 = new_circle (probe_center, this_srf -> probe_radius, circle4_axis); if (circle4 == NULL) return; link_circle (this_srf, circle4); circle4 -> theta = 0.0; circle4 -> subtype = GREAT_SUBTYPE; } else circle4 = NULL; /* set up arcs */ arc1 = new_arc (circle1, vertex1, vertex2, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc1 == NULL) return; this_srf -> n_arc++; arc2 = new_arc (circle2, vertex2, vertex3, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc2 == NULL) return; this_srf -> n_arc++; if (circle4 == NULL) { arc3 = new_arc (circle3, vertex3, vertex1, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc3 == NULL) return; this_srf -> n_arc++; arc4 = NULL; } else if (circle4 != NULL) { arc3 = new_arc (circle3, vertex3, vertex4, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc3 == NULL) return; this_srf -> n_arc++; arc4 = new_arc (circle4, vertex4, vertex1, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc4 == NULL) return; this_srf -> n_arc++; } /* add arcs to tori */ arc1 -> next = torus1 -> first_arc; torus1 -> first_arc = arc1; sprintf (message, "%8ld %8ld torus: add arc", torus1 -> sph[0] -> number, torus1 -> sph[1] -> number); informd2(message); arc2 -> next = torus2 -> first_arc; torus2 -> first_arc = arc2; sprintf (message, "%8ld %8ld torus: add arc", torus2 -> sph[0] -> number, torus2 -> sph[1] -> number); informd2(message); arc3 -> next = torus3 -> first_arc; torus3 -> first_arc = arc3; sprintf (message, "%8ld %8ld torus: add arc", torus3 -> sph[0] -> number, torus3 -> sph[1] -> number); informd2(message); if (torus4 != NULL) { arc4 -> next = torus4 -> first_arc; torus4 -> first_arc = arc4; sprintf (message, "%8ld %8ld torus: add arc", torus4 -> sph[0] -> number, torus4 -> sph[1] -> number); informd(message); } /* new concave face */ concave_fac = new_face (NULL, CONCAVE); if (concave_fac == NULL) return; concave_fac -> ptr.prb = prb; concave_fac -> chi = 1; link_face (this_srf, concave_fac); add2face (concave_fac, arc1, arc2, arc3, arc4); /* back pointer for cusp corrections */ prb -> fac = concave_fac; arc1 -> fac = concave_fac; arc2 -> fac = concave_fac; arc3 -> fac = concave_fac; if (arc4 != NULL) { arc4 -> fac = concave_fac; } }
void LineBuilder::build() { // Need at least 2 points to draw a line if (points.size() < 2) { clear_output(); return; } const float hw = width / 2.f; const float hw_sq = hw * hw; const float sharp_limit_sq = sharp_limit * sharp_limit; const int len = points.size(); // Initial values Vector2 pos0 = points[0]; Vector2 pos1 = points[1]; Vector2 f0 = (pos1 - pos0).normalized(); Vector2 u0 = rotate90(f0); Vector2 pos_up0 = pos0 + u0 * hw; Vector2 pos_down0 = pos0 - u0 * hw; Color color0; Color color1; float current_distance0 = 0.f; float current_distance1 = 0.f; float total_distance; _interpolate_color = gradient != NULL; bool distance_required = _interpolate_color || texture_mode == LINE_TEXTURE_TILE; if (distance_required) total_distance = calculate_total_distance(points); if (_interpolate_color) color0 = gradient->get_color(0); else colors.push_back(default_color); float uvx0 = 0.f; float uvx1 = 0.f; // Begin cap if (begin_cap_mode == LINE_CAP_BOX) { // Push back first vertices a little bit pos_up0 -= f0 * hw; pos_down0 -= f0 * hw; // The line's outer length will be a little higher due to begin and end caps total_distance += width; current_distance0 += hw; current_distance1 = current_distance0; } else if (begin_cap_mode == LINE_CAP_ROUND) { if (texture_mode == LINE_TEXTURE_TILE) { uvx0 = 0.5f; } new_arc(pos0, pos_up0 - pos0, -Math_PI, color0, Rect2(0.f, 0.f, 1.f, 1.f)); total_distance += width; current_distance0 += hw; current_distance1 = current_distance0; } strip_begin(pos_up0, pos_down0, color0, uvx0); // pos_up0 ------------- pos_up1 -------------------- // | | // pos0 - - - - - - - - - pos1 - - - - - - - - - pos2 // | | // pos_down0 ------------ pos_down1 ------------------ // // i-1 i i+1 // http://labs.hyperandroid.com/tag/opengl-lines // (not the same implementation but visuals help a lot) // For each additional segment for (int i = 1; i < len - 1; ++i) { pos1 = points[i]; Vector2 pos2 = points[i + 1]; Vector2 f1 = (pos2 - pos1).normalized(); Vector2 u1 = rotate90(f1); // Determine joint orientation const float dp = u0.dot(f1); const Orientation orientation = (dp > 0.f ? UP : DOWN); Vector2 inner_normal0, inner_normal1; if (orientation == UP) { inner_normal0 = u0 * hw; inner_normal1 = u1 * hw; } else { inner_normal0 = -u0 * hw; inner_normal1 = -u1 * hw; } // --------------------------- // / // 0 / 1 // / / // --------------------x------ / // / / (here shown with orientation == DOWN) // / / // / / // / / // 2 / // / // Find inner intersection at the joint Vector2 corner_pos_in, corner_pos_out; SegmentIntersectionResult intersection_result = segment_intersection( pos0 + inner_normal0, pos1 + inner_normal0, pos1 + inner_normal1, pos2 + inner_normal1, &corner_pos_in); if (intersection_result == SEGMENT_INTERSECT) // Inner parts of the segments intersect corner_pos_out = 2.f * pos1 - corner_pos_in; else { // No intersection, segments are either parallel or too sharp corner_pos_in = pos1 + inner_normal0; corner_pos_out = pos1 - inner_normal0; } Vector2 corner_pos_up, corner_pos_down; if (orientation == UP) { corner_pos_up = corner_pos_in; corner_pos_down = corner_pos_out; } else { corner_pos_up = corner_pos_out; corner_pos_down = corner_pos_in; } LineJointMode current_joint_mode = joint_mode; Vector2 pos_up1, pos_down1; if (intersection_result == SEGMENT_INTERSECT) { // Fallback on bevel if sharp angle is too high (because it would produce very long miters) if (current_joint_mode == LINE_JOINT_SHARP && corner_pos_out.distance_squared_to(pos1) / hw_sq > sharp_limit_sq) { current_joint_mode = LINE_JOINT_BEVEL; } if (current_joint_mode == LINE_JOINT_SHARP) { // In this case, we won't create joint geometry, // The previous and next line quads will directly share an edge. pos_up1 = corner_pos_up; pos_down1 = corner_pos_down; } else { // Bevel or round if (orientation == UP) { pos_up1 = corner_pos_up; pos_down1 = pos1 - u0 * hw; } else { pos_up1 = pos1 + u0 * hw; pos_down1 = corner_pos_down; } } } else { // No intersection: fallback pos_up1 = corner_pos_up; pos_down1 = corner_pos_down; } // Add current line body quad // Triangles are clockwise if (distance_required) { current_distance1 += pos0.distance_to(pos1); } if (_interpolate_color) { color1 = gradient->get_color_at_offset(current_distance1 / total_distance); } if (texture_mode == LINE_TEXTURE_TILE) { uvx0 = current_distance0 / width; uvx1 = current_distance1 / width; } strip_add_quad(pos_up1, pos_down1, color1, uvx1); // Swap vars for use in the next line color0 = color1; u0 = u1; f0 = f1; pos0 = pos1; current_distance0 = current_distance1; if (intersection_result == SEGMENT_INTERSECT) { if (current_joint_mode == LINE_JOINT_SHARP) { pos_up0 = pos_up1; pos_down0 = pos_down1; } else { if (orientation == UP) { pos_up0 = corner_pos_up; pos_down0 = pos1 - u1 * hw; } else { pos_up0 = pos1 + u1 * hw; pos_down0 = corner_pos_down; } } } else { pos_up0 = pos1 + u1 * hw; pos_down0 = pos1 - u1 * hw; } // From this point, bu0 and bd0 concern the next segment // Add joint geometry if (current_joint_mode != LINE_JOINT_SHARP) { // ________________ cbegin // / \ // / \ // ____________/_ _ _\ cend // | | // | | // | | Vector2 cbegin, cend; if (orientation == UP) { cbegin = pos_down1; cend = pos_down0; } else { cbegin = pos_up1; cend = pos_up0; } if (current_joint_mode == LINE_JOINT_BEVEL) { strip_add_tri(cend, orientation); } else if (current_joint_mode == LINE_JOINT_ROUND) { Vector2 vbegin = cbegin - pos1; Vector2 vend = cend - pos1; strip_add_arc(pos1, vend.angle_to(vbegin), orientation); } if (intersection_result != SEGMENT_INTERSECT) // In this case the joint is too f****d up to be re-used, // start again the strip with fallback points strip_begin(pos_up0, pos_down0, color1, uvx1); } } // Last (or only) segment pos1 = points[points.size() - 1]; Vector2 pos_up1 = pos1 + u0 * hw; Vector2 pos_down1 = pos1 - u0 * hw; // End cap (box) if (end_cap_mode == LINE_CAP_BOX) { pos_up1 += f0 * hw; pos_down1 += f0 * hw; } if (distance_required) { current_distance1 += pos0.distance_to(pos1); } if (_interpolate_color) { color1 = gradient->get_color(gradient->get_points_count() - 1); } if (texture_mode == LINE_TEXTURE_TILE) { uvx1 = current_distance1 / width; } strip_add_quad(pos_up1, pos_down1, color1, uvx1); // End cap (round) if (end_cap_mode == LINE_CAP_ROUND) { // Note: color is not used in case we don't interpolate... Color color = _interpolate_color ? gradient->get_color(gradient->get_points_count() - 1) : Color(0, 0, 0); new_arc(pos1, pos_up1 - pos1, Math_PI, color, Rect2(uvx1 - 0.5f, 0.f, 1.f, 1.f)); } }