Example #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;
  }
}
Example #2
0
void
transform_length (real *len, const DiaMatrix *m)
{
  Point pt = { *len, 0 };
  transform_point (&pt, m);
  /* not interested in the offset */
  pt.x -= m->x0;
  pt.y -= m->y0;
  *len = point_len (&pt);
}
Example #3
0
File: arc.c Project: mpuels/dia
/** rotates p around the center by an angle given in radians 
 * a positive angle is ccw on the screen*/
static void
rotate_point_around_point(Point *p, const Point *center, real angle)
{
        real radius;
        real a;
        point_sub(p,center);
        radius = point_len(p);
        a = -atan2(p->y,p->x); /* y axis points down*/
        a += angle;
        p->x = cos(a); p->y = -sin(a);/* y axis points down*/
        point_scale(p,radius);
        point_add(p,center);
}
Example #4
0
File: bezier.c Project: GNOME/dia
static real approx_bez_length(BezierConn *bez)
{
        /* Approximates the length of the bezier curve
         * by the length of the polyline joining its points */
        Point *current, *last, vec;
        real length = .0;
        int i;
        current = &bez->bezier.points[0].p1;
        for (i=1; i < bez->bezier.num_points ; i++){
            last = current;
            current = &bez->bezier.points[i].p3;
            point_copy(&vec,last);
            point_sub(&vec,current);
            length += point_len(&vec);
        }
        return length;
}
Example #5
0
void 
connpointline_putonaline(ConnPointLine *cpl,Point *start,Point *end, gint dirs)
{
  Point se_vector;
  real se_len,pseudopoints;
  int i;
  GSList *elem;

  point_copy(&se_vector, end);
  point_sub(&se_vector, start);
  
  se_len = point_len(&se_vector);
  
  if (se_len > 0)
    point_normalize(&se_vector);
  
  cpl->start = *start;
  cpl->end = *end;
  
  if (dirs != DIR_NONE)
    /* use the oone givne by the caller */;
  else if (fabs(se_vector.x) > fabs(se_vector.y))
    dirs = DIR_NORTH|DIR_SOUTH;
  else
    dirs = DIR_EAST|DIR_WEST;

  pseudopoints = cpl->num_connections + 1; /* here, we count the start and end 
					    points as eating real positions. */
  for (i=0, elem=cpl->connections; 
       i<cpl->num_connections; 
       i++,elem=g_slist_next(elem)) {
    ConnectionPoint *cp = (ConnectionPoint *)(elem->data);
    cp->pos = se_vector;
    cp->directions = dirs;
    point_scale(&cp->pos,se_len * (i+1.0)/pseudopoints);
    point_add(&cp->pos,start);
  }
}
Example #6
0
ObjectChange *
beziershape_move_handle(BezierShape *bezier, Handle *handle,
			Point *to, ConnectionPoint *cp,
			HandleMoveReason reason, ModifierKeys modifiers)
{
  int handle_nr, comp_nr, next_nr, prev_nr;
  Point delta, pt;
  
  delta = *to;
  point_sub(&delta, &handle->pos);

  handle_nr = get_handle_nr(bezier, handle);
  comp_nr = get_comp_nr(handle_nr);
  next_nr = comp_nr + 1;
  prev_nr = comp_nr - 1;
  if (comp_nr == bezier->numpoints - 1)
    next_nr = 1;
  if (comp_nr == 1)
    prev_nr = bezier->numpoints - 1;
  
  switch(handle->id) {
  case HANDLE_BEZMAJOR:
    if (comp_nr == bezier->numpoints - 1) {
      bezier->points[comp_nr].p3 = *to;
      bezier->points[0].p1 = bezier->points[0].p3 = *to;
      point_add(&bezier->points[comp_nr].p2, &delta);
      point_add(&bezier->points[1].p1, &delta);
    } else {
      bezier->points[comp_nr].p3 = *to;
      point_add(&bezier->points[comp_nr].p2, &delta);
      point_add(&bezier->points[comp_nr+1].p1, &delta);
    }
    break;
  case HANDLE_LEFTCTRL:
    bezier->points[comp_nr].p2 = *to;
    switch (bezier->corner_types[comp_nr]) {
    case BEZ_CORNER_SYMMETRIC:
      pt = bezier->points[comp_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p2);
      point_add(&pt, &bezier->points[comp_nr].p3);
      bezier->points[next_nr].p1 = pt;
      break;
    case BEZ_CORNER_SMOOTH: {
      real len;

      pt = bezier->points[next_nr].p1;
      point_sub(&pt, &bezier->points[comp_nr].p3);
      len = point_len(&pt);

      pt = bezier->points[comp_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p2);
      if (point_len(&pt) > 0)
	point_normalize(&pt);
      else {
	pt.x = 1.0; pt.y = 0.0;
      }
      point_scale(&pt, len);
      point_add(&pt, &bezier->points[comp_nr].p3);
      bezier->points[next_nr].p1 = pt;
      break;
    }
    case BEZ_CORNER_CUSP:
      /* no mirror point movement required */
      break;
    }
    break;
  case HANDLE_RIGHTCTRL:
    bezier->points[comp_nr].p1 = *to;
    switch (bezier->corner_types[prev_nr]) {
    case BEZ_CORNER_SYMMETRIC:
      pt = bezier->points[prev_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p1);
      point_add(&pt, &bezier->points[prev_nr].p3);
      bezier->points[prev_nr].p2 = pt;
      break;
    case BEZ_CORNER_SMOOTH: {
      real len;

      pt = bezier->points[prev_nr].p2;
      point_sub(&pt, &bezier->points[prev_nr].p3);
      len = point_len(&pt);

      pt = bezier->points[prev_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p1);
      if (point_len(&pt) > 0)
	point_normalize(&pt);
      else {
	pt.x = 1.0; pt.y = 0.0;
      }
      point_scale(&pt, len);
      point_add(&pt, &bezier->points[prev_nr].p3);
      bezier->points[prev_nr].p2 = pt;
      break;
    }
    case BEZ_CORNER_CUSP:
      /* no mirror point movement required */
      break;
    }
    break;
  default:
    message_error("Internal error in beziershape_move_handle.");
    break;
  }
  return NULL;
}
Example #7
0
static void
wanlink_update_data(WanLink *wanlink)
{
  Connection *conn = &wanlink->connection;
  DiaObject *obj = (DiaObject *) wanlink;
  Point v, vhat;
  Point *endpoints;
  real width, width_2;
  real len, angle;
  Point origin;
  int i;
  Matrix m;
  

  width = wanlink->width;
  width_2 = width / 2.0;
  
  if (connpoint_is_autogap(conn->endpoint_handles[0].connected_to) ||
      connpoint_is_autogap(conn->endpoint_handles[1].connected_to)) {
    connection_adjust_for_autogap(conn);
  }
  endpoints = &conn->endpoints[0]; 
  obj->position = endpoints[0];

  v = endpoints[1];
  point_sub(&v, &endpoints[0]);
  if ((fabs(v.x) == 0.0) && (fabs(v.y)==0.0)) {
    v.x += 0.01;
  }
  vhat = v;
  point_normalize(&vhat);

  connection_update_boundingbox(conn);

  /** compute the polygon **/
  origin = wanlink->connection.endpoints [0];
  len = point_len (&v);

  angle = atan2 (vhat.y, vhat.x) - M_PI_2;

    /* The case of the wanlink */
  wanlink->poly[0].x = (width * 0.50) - width_2;
  wanlink->poly[0].y = (len * 0.00);
  wanlink->poly[1].x = (width * 0.50) - width_2;
  wanlink->poly[1].y = (len * 0.45);
  wanlink->poly[2].x = (width * 0.94) - width_2;
  wanlink->poly[2].y = (len * 0.45);
  wanlink->poly[3].x = (width * 0.50) - width_2;
  wanlink->poly[3].y = (len * 1.00);
  wanlink->poly[4].x = (width * 0.50) - width_2;
  wanlink->poly[4].y = (len * 0.55);
  wanlink->poly[5].x = (width * 0.06) - width_2;
  wanlink->poly[5].y = (len * 0.55);
  
  /* rotate */
  _identity_matrix (m);
  _rotate_matrix (m, angle);

  obj->bounding_box.top = origin.y;
  obj->bounding_box.left = origin.x;
  obj->bounding_box.bottom = conn->endpoints[1].y;
  obj->bounding_box.right = conn->endpoints[1].x;
  for (i = 0; i <  WANLINK_POLY_LEN; i++) 
  {
      Point new_pt;
      
      _transform_point (m, &wanlink->poly[i], 
		        &new_pt);
      point_add (&new_pt, &origin);
      wanlink->poly[i] = new_pt;
  }
  /* calculate bounding box */
  {
    PolyBBExtras bbex = {0, 0, wanlink->width/2, 0, 0 };
    polyline_bbox (&wanlink->poly[0], WANLINK_POLY_LEN, &bbex, TRUE, &obj->bounding_box);
  }


  connection_update_handles(conn);
}
Example #8
0
/*!
 * \brief Move one of the handles associated with the
 * @param bezier The object whose handle is being moved.
 * @param handle The handle being moved.
 * @param to The position it has been moved to (corrected for
 *   vertical/horizontal only movement).
 * @param cp If non-NULL, the connectionpoint found at this position.
 *   If @a cp is NULL, there may or may not be a connectionpoint.
 * @param reason ignored
 * @param modifiers ignored
 * @return NULL
 * \memberof BezierConn
 */
ObjectChange*
bezierconn_move_handle (BezierConn *bezier,
			Handle *handle,
			Point *to,
			ConnectionPoint *cp,
			HandleMoveReason reason,
			ModifierKeys modifiers)
{
  int handle_nr, comp_nr;
  Point delta, pt;
  
  delta = *to;
  point_sub(&delta, &handle->pos);

  handle_nr = get_handle_nr(bezier, handle);
  comp_nr = get_comp_nr(handle_nr);
  switch(handle->id) {
  case HANDLE_MOVE_STARTPOINT:
    bezier->bezier.points[0].p1 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[1].p1, &delta);
    break;
  case HANDLE_MOVE_ENDPOINT:
    bezier->bezier.points[bezier->bezier.num_points-1].p3 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[bezier->bezier.num_points-1].p2, &delta);
    break;
  case HANDLE_BEZMAJOR:
    bezier->bezier.points[comp_nr].p3 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[comp_nr].p2, &delta);
    point_add(&bezier->bezier.points[comp_nr+1].p1, &delta);
    break;
  case HANDLE_LEFTCTRL:
    bezier->bezier.points[comp_nr].p2 = *to;
    if (comp_nr < bezier->bezier.num_points - 1) {
      switch (bezier->bezier.corner_types[comp_nr]) {
      case BEZ_CORNER_SYMMETRIC:
	pt = bezier->bezier.points[comp_nr].p3;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p2);
	point_add(&pt, &bezier->bezier.points[comp_nr].p3);
	bezier->bezier.points[comp_nr+1].p1 = pt;
	break;
      case BEZ_CORNER_SMOOTH: {
	real len;
	pt = bezier->bezier.points[comp_nr+1].p1;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p3);
	len = point_len(&pt);
	pt = bezier->bezier.points[comp_nr].p2;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p3);
	if (point_len(&pt) > 0)
	  point_normalize(&pt);
	else { pt.x = 1.0; pt.y = 0.0; }
	point_scale(&pt, -len);
	point_add(&pt, &bezier->bezier.points[comp_nr].p3);
	bezier->bezier.points[comp_nr+1].p1 = pt;
	break;
      }	
      case BEZ_CORNER_CUSP:
	/* Do nothing to the other guy */
	break;
      }
    }
    break;
  case HANDLE_RIGHTCTRL:
    bezier->bezier.points[comp_nr].p1 = *to;
    if (comp_nr > 1) {
      switch (bezier->bezier.corner_types[comp_nr-1]) {
      case BEZ_CORNER_SYMMETRIC:
	pt = bezier->bezier.points[comp_nr - 1].p3;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p1);
	point_add(&pt, &bezier->bezier.points[comp_nr - 1].p3);
	bezier->bezier.points[comp_nr-1].p2 = pt;
	break;
      case BEZ_CORNER_SMOOTH: {
	real len;
	pt = bezier->bezier.points[comp_nr-1].p2;
	point_sub(&pt, &bezier->bezier.points[comp_nr-1].p3);
	len = point_len(&pt);
	pt = bezier->bezier.points[comp_nr].p1;
	point_sub(&pt, &bezier->bezier.points[comp_nr-1].p3);
	if (point_len(&pt) > 0)
	  point_normalize(&pt);
	else { pt.x = 1.0; pt.y = 0.0; }
	point_scale(&pt, -len);
	point_add(&pt, &bezier->bezier.points[comp_nr-1].p3);
	bezier->bezier.points[comp_nr-1].p2 = pt;
	break;
      }	
      case BEZ_CORNER_CUSP:
	/* Do nothing to the other guy */
	break;
      }
    }
    break;
  default:
    g_warning("Internal error in bezierconn_move_handle.\n");
    break;
  }
  return NULL;
}