Ejemplo n.º 1
0
/*!
 * \brief Limit movability of control handles
 *
 * Update a corner to have less freedom in its control handles, arranging
 * the control points at some reasonable places.
 * @param bezier A bezierconn to straighten a corner of
 * @param comp_nr The index into the corner_types array of the corner to
 *                straighten.
 * \memberof _BezierConn
 */
static void
bezierconn_straighten_corner (BezierConn *bezier, int comp_nr)
{
  int next_nr = comp_nr+1;
  /* Neat thing would be to have the kind of straigthening depend on
     which handle was chosen:  Mid-handle does average, other leaves that
     handle where it is. */
  switch (bezier->bezier.corner_types[comp_nr]) {
  case BEZ_CORNER_SYMMETRIC: {
    Point pt1, pt2;

    pt1 = bezier->bezier.points[comp_nr].p3;
    point_sub(&pt1, &bezier->bezier.points[comp_nr].p2);
    pt2 = bezier->bezier.points[comp_nr].p3;
    point_sub(&pt2, &bezier->bezier.points[next_nr].p1);
    point_scale(&pt2, -1.0);
    point_add(&pt1, &pt2);
    point_scale(&pt1, 0.5);
    pt2 = pt1;
    point_scale(&pt1, -1.0);
    point_add(&pt1, &bezier->bezier.points[comp_nr].p3);
    point_add(&pt2, &bezier->bezier.points[comp_nr].p3);
    bezier->bezier.points[comp_nr].p2 = pt1;
    bezier->bezier.points[next_nr].p1 = pt2;
    bezierconn_update_data(bezier);
  }
  break;
  case BEZ_CORNER_SMOOTH: {
    Point pt1, pt2;
    real len1, len2;
    pt1 = bezier->bezier.points[comp_nr].p3;
    point_sub(&pt1, &bezier->bezier.points[comp_nr].p2);
    pt2 = bezier->bezier.points[comp_nr].p3;
    point_sub(&pt2, &bezier->bezier.points[next_nr].p1);
    len1 = point_len(&pt1);
    len2 = point_len(&pt2);
    point_scale(&pt2, -1.0);
    if (len1 > 0)
      point_normalize(&pt1);
    if (len2 > 0)
      point_normalize(&pt2);
    point_add(&pt1, &pt2);
    point_scale(&pt1, 0.5);
    pt2 = pt1;
    point_scale(&pt1, -len1);
    point_add(&pt1, &bezier->bezier.points[comp_nr].p3);
    point_scale(&pt2, len2);
    point_add(&pt2, &bezier->bezier.points[comp_nr].p3);
    bezier->bezier.points[comp_nr].p2 = pt1;
    bezier->bezier.points[next_nr].p1 = pt2;
    bezierconn_update_data(bezier);
  }
    break;
  case BEZ_CORNER_CUSP:
    break;
  }
}
Ejemplo n.º 2
0
static void
bezierline_update_data(Bezierline *bezierline)
{
    BezierConn *bez = &bezierline->bez;
    Object *obj = (Object *) bezierline;

    bezierconn_update_data(bez);

    bezierconn_update_boundingbox(bez);
    /* fix boundingbox for line_width: */
    obj->bounding_box.top -= bezierline->line_width/2;
    obj->bounding_box.left -= bezierline->line_width/2;
    obj->bounding_box.bottom += bezierline->line_width/2;
    obj->bounding_box.right += bezierline->line_width/2;

    /* Fix boundingbox for arrowheads */
    if (bezierline->start_arrow.type != ARROW_NONE ||
            bezierline->end_arrow.type != ARROW_NONE) {
        real arrow_width = 0.0;
        if (bezierline->start_arrow.type != ARROW_NONE)
            arrow_width = bezierline->start_arrow.width;
        if (bezierline->end_arrow.type != ARROW_NONE)
            arrow_width = MAX(arrow_width, bezierline->start_arrow.width);

        obj->bounding_box.top -= arrow_width;
        obj->bounding_box.left -= arrow_width;
        obj->bounding_box.bottom += arrow_width;
        obj->bounding_box.right += arrow_width;
    }

    obj->position = bez->points[0].p1;
}
Ejemplo n.º 3
0
/*!
 * \brief Remove a segment from a bezier.
 * @param bezier The bezier to remove a segment from.
 * @param pos The index of the segment to remove.
 * @returns Undo information for the segment removal.
 * \memberof _BezierConn
 */
ObjectChange *
bezierconn_remove_segment (BezierConn *bezier, int pos)
{
  Handle *old_handle1, *old_handle2, *old_handle3;
  ConnectionPoint *cpt1, *cpt2, *cpt3;
  BezPoint old_point;
  BezCornerType old_ctype;
  int next;

  g_assert(pos > 0);
  g_assert(bezier->bezier.num_points > 2);

  if (pos == bezier->bezier.num_points-1)
    pos--;
  next = pos+1;

  old_handle1 = bezier->object.handles[3*pos-2];
  old_handle2 = bezier->object.handles[3*pos-1];
  old_handle3 = bezier->object.handles[3*pos];
  old_point = bezier->bezier.points[pos];
  /* remember the old control point of following bezpoint */
  old_point.p1 = bezier->bezier.points[next].p1;
  old_ctype = bezier->bezier.corner_types[pos];

  cpt1 = old_handle1->connected_to;
  cpt2 = old_handle2->connected_to;
  cpt3 = old_handle3->connected_to;
  
  object_unconnect((DiaObject *)bezier, old_handle1);
  object_unconnect((DiaObject *)bezier, old_handle2);
  object_unconnect((DiaObject *)bezier, old_handle3);

  remove_handles(bezier, pos);

  bezierconn_update_data(bezier);
  
  return bezierconn_create_point_change(bezier, TYPE_REMOVE_POINT,
					&old_point, old_ctype, pos,
					old_handle1, cpt1,
					old_handle2, cpt2,
					old_handle3, cpt3);
}
Ejemplo n.º 4
0
Archivo: bezier.c Proyecto: GNOME/dia
static void
bezierline_update_data(Bezierline *bezierline)
{
  BezierConn *bez = &bezierline->bez;
  DiaObject *obj = &bez->object;
  PolyBBExtras *extra = &bez->extra_spacing;

  bezierconn_update_data(bez);

  extra->start_trans = extra->start_long =
  extra->middle_trans =
  extra->end_trans = extra->end_long = (bezierline->line_width / 2.0);

  obj->position = bez->bezier.points[0].p1;

  if (connpoint_is_autogap(bez->object.handles[0]->connected_to) ||
      connpoint_is_autogap(bez->object.handles[3*(bez->bezier.num_points-1)]->connected_to) ||
      bezierline->absolute_start_gap || bezierline->absolute_end_gap ||
      bezierline->start_arrow.type != ARROW_NONE || bezierline->end_arrow.type != ARROW_NONE) {
    Point gap_points[4];
    Rectangle bbox_union = {bez->bezier.points[0].p1.x, bez->bezier.points[0].p1.y,
			    bez->bezier.points[0].p1.x, bez->bezier.points[0].p1.y};
    compute_gap_points(bezierline, gap_points);
    exchange_bez_gap_points(bez,gap_points);
    /* further modifying the points data, accounts for corrcet arrow and bezier bounding box */
    if (bezierline->start_arrow.type != ARROW_NONE) {
      Rectangle bbox;
      Point move_arrow, move_line;
      Point to = bez->bezier.points[0].p1, from = bez->bezier.points[1].p1;

      calculate_arrow_point(&bezierline->start_arrow, &to, &from, &move_arrow, &move_line, bezierline->line_width);
      point_sub(&to, &move_arrow);
      point_sub(&bez->bezier.points[0].p1, &move_line);
      arrow_bbox (&bezierline->start_arrow, bezierline->line_width, &to, &from, &bbox);
      rectangle_union (&bbox_union, &bbox);
    }
    if (bezierline->end_arrow.type != ARROW_NONE) {
      Rectangle bbox;
      Point move_arrow, move_line;
      int num_points = bez->bezier.num_points;
      Point to = bez->bezier.points[num_points-1].p3, from = bez->bezier.points[num_points-1].p2;

      calculate_arrow_point(&bezierline->end_arrow, &to, &from, &move_arrow, &move_line, bezierline->line_width);
      point_sub(&to, &move_arrow);
      point_sub(&bez->bezier.points[num_points-1].p3, &move_line);
      arrow_bbox (&bezierline->end_arrow, bezierline->line_width, &to, &from, &bbox);
      rectangle_union (&bbox_union, &bbox);
    }
    bezierconn_update_boundingbox(bez);
    rectangle_union (&obj->bounding_box, &bbox_union);
    exchange_bez_gap_points(bez,gap_points);
  } else {
    bezierconn_update_boundingbox(bez);
  }
    /* add control points to the bounding box, needed to make them visible when showing all
      * and to remove traces from them */
  {
    int i, num_points = bez->bezier.num_points;
    g_assert (obj->enclosing_box != NULL);
    *obj->enclosing_box = obj->bounding_box;
    /* starting with the second point, the first one is MOVE_TO */
    for (i = 1; i < num_points; ++i) {
      if (bez->bezier.points[i].type != BEZ_CURVE_TO)
        continue;
      rectangle_add_point(obj->enclosing_box, &bez->bezier.points[i].p1);
      rectangle_add_point(obj->enclosing_box, &bez->bezier.points[i].p2);
    }
  }
}
Ejemplo n.º 5
0
Archivo: bezier.c Proyecto: GNOME/dia
static void
bezierline_select(Bezierline *bezierline, Point *clicked_point,
		  DiaRenderer *interactive_renderer)
{
  bezierconn_update_data(&bezierline->bez);
}