static DiaObject * zigzagline_create(Point *startpoint, void *user_data, Handle **handle1, Handle **handle2) { Zigzagline *zigzagline; OrthConn *orth; DiaObject *obj; Point dummy = {0, 0}; /*zigzagline_init_defaults();*/ zigzagline = g_malloc0(sizeof(Zigzagline)); orth = &zigzagline->orth; obj = &orth->object; obj->type = &zigzagline_type; obj->ops = &zigzagline_ops; if (startpoint) orthconn_init(orth, startpoint); else orthconn_init(orth, &dummy); if (user_data) { MultipointCreateData *pcd = (MultipointCreateData *)user_data; orthconn_set_points (orth, pcd->num_points, pcd->points); } zigzagline->line_width = attributes_get_default_linewidth(); zigzagline->line_color = attributes_get_foreground(); attributes_get_default_line_style(&zigzagline->line_style, &zigzagline->dashlength); zigzagline->line_join = LINEJOIN_MITER; zigzagline->line_caps = LINECAPS_BUTT; zigzagline->start_arrow = attributes_get_default_start_arrow(); zigzagline->end_arrow = attributes_get_default_end_arrow(); zigzagline->corner_radius = 0.0; *handle1 = orth->handles[0]; *handle2 = orth->handles[orth->numpoints-2]; zigzagline_update_data(zigzagline); return &zigzagline->orth.object; }
/** Calculate a 'pleasing' route between two connection points. * If a good route is found, updates the given OrthConn with the values * and returns TRUE. * Otherwise, the OrthConn is untouched, and the function returns FALSE. * Handles are not updated by this operation. * @param conn The orthconn object to autoroute for. * @param startconn The connectionpoint at the start of the orthconn, * or null if it is not connected there at the moment. * @param endconn The connectionpoint at the end (target) of the orthconn, * or null if it is not connected there at the moment. * @returns TRUE if the orthconn could be laid out reasonably, FALSE otherwise. */ gboolean autoroute_layout_orthconn(OrthConn *conn, ConnectionPoint *startconn, ConnectionPoint *endconn) { real min_badness = MAX_BADNESS; Point *best_layout = NULL; guint best_num_points = 0; int startdir, enddir; int fromdir, todir; Point frompos, topos; frompos = conn->points[0]; topos = conn->points[conn->numpoints-1]; if (startconn != NULL) { fromdir = startconn->directions; frompos = startconn->pos; } else fromdir = DIR_NORTH|DIR_EAST|DIR_SOUTH|DIR_WEST; if (endconn != NULL) { todir = endconn->directions; topos = endconn->pos; } else todir = DIR_NORTH|DIR_EAST|DIR_SOUTH|DIR_WEST; for (startdir = DIR_NORTH; startdir <= DIR_WEST; startdir *= 2) { for (enddir = DIR_NORTH; enddir <= DIR_WEST; enddir *= 2) { if ((fromdir & startdir) && (todir & enddir)) { real this_badness; Point *this_layout = NULL; guint this_num_points; guint normal_enddir; Point startpoint, endpoint; Point otherpoint; startpoint = autolayout_adjust_for_gap(&frompos, startdir, startconn); autolayout_adjust_for_arrow(&startpoint, startdir, conn->extra_spacing.start_trans); endpoint = autolayout_adjust_for_gap(&topos, enddir, endconn); autolayout_adjust_for_arrow(&endpoint, enddir, conn->extra_spacing.end_trans); /* printf("Startdir %d enddir %d orgstart %.2f, %.2f orgend %.2f, %.2f start %.2f, %.2f end %.2f, %.2f\n", startdir, enddir, frompos.x, frompos.y, topos.x, topos.y, startpoint.x, startpoint.y, endpoint.x, endpoint.y); */ normal_enddir = autolayout_normalize_points(startdir, enddir, startpoint, endpoint, &otherpoint); if (normal_enddir == DIR_NORTH ) { this_badness = autoroute_layout_parallel(&otherpoint, &this_num_points, &this_layout); } else if (normal_enddir == DIR_SOUTH) { this_badness = autoroute_layout_opposite(&otherpoint, &this_num_points, &this_layout); } else { this_badness = autoroute_layout_orthogonal(&otherpoint, normal_enddir, &this_num_points, &this_layout); } if (this_layout != NULL) { if (this_badness-min_badness < -0.00001) { /* printf("Dir %d to %d badness %f < %f\n", startdir, enddir, this_badness, min_badness); */ min_badness = this_badness; if (best_layout != NULL) g_free(best_layout); best_layout = autolayout_unnormalize_points(startdir, startpoint, this_layout, this_num_points); best_num_points = this_num_points; /* revert adjusting start and end point */ autolayout_adjust_for_arrow(&best_layout[0], startdir, -conn->extra_spacing.start_trans); autolayout_adjust_for_arrow(&best_layout[best_num_points-1], enddir, -conn->extra_spacing.end_trans); } else { g_free(this_layout); } } } } } if (min_badness < MAX_BADNESS) { orthconn_set_points(conn, best_num_points, best_layout); g_free(best_layout); return TRUE; } else { g_free(best_layout); return FALSE; } }