Пример #1
0
/**
 * @name pick_close_point
 *
 * Choose the edge point that is closest to the critical point.  This
 * point may not be exactly vertical from the critical point.
 */
EDGEPT *Wordrec::pick_close_point(EDGEPT *critical_point,
                                  EDGEPT *vertical_point,
                                  int *best_dist) {
  EDGEPT *best_point = nullptr;
  int this_distance;
  int found_better;

  do {
    found_better = false;

    this_distance = edgept_dist (critical_point, vertical_point);
    if (this_distance <= *best_dist) {

      if (!(same_point (critical_point->pos, vertical_point->pos) ||
        same_point (critical_point->pos, vertical_point->next->pos) ||
        (best_point && same_point (best_point->pos, vertical_point->pos)) ||
      is_exterior_point (critical_point, vertical_point))) {
        *best_dist = this_distance;
        best_point = vertical_point;
        if (chop_vertical_creep)
          found_better = true;
      }
    }
    vertical_point = vertical_point->next;
  }
  while (found_better == true);

  return (best_point);
}
Пример #2
0
/**
 * @name vertical_projection_point
 *
 * For one point on the outline, find the corresponding point on the
 * other side of the outline that is a likely projection for a split
 * point.  This is done by iterating through the edge points until the
 * X value of the point being looked at is greater than the X value of
 * the split point.  Ensure that the point being returned is not right
 * next to the split point.  Return the edge point in *best_point as
 * a result, and any points that were newly created are also saved on
 * the new_points list.
 */
void Wordrec::vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point,
                                        EDGEPT** best_point,
                                        EDGEPT_CLIST *new_points) {
  EDGEPT *p;                     /* Iterator */
  EDGEPT *this_edgept;           /* Iterator */
  EDGEPT_C_IT new_point_it(new_points);
  int x = split_point->pos.x;    /* X value of vertical */
  int best_dist = LARGE_DISTANCE;/* Best point found */

  if (*best_point != nullptr)
    best_dist = edgept_dist(split_point, *best_point);

  p = target_point;
  /* Look at each edge point */
  do {
    if (((p->pos.x <= x && x <= p->next->pos.x) ||
         (p->next->pos.x <= x && x <= p->pos.x)) &&
        !same_point(split_point->pos, p->pos) &&
        !same_point(split_point->pos, p->next->pos) &&
        !p->IsChopPt() &&
        (*best_point == nullptr || !same_point((*best_point)->pos, p->pos))) {

      if (near_point(split_point, p, p->next, &this_edgept)) {
        new_point_it.add_before_then_move(this_edgept);
      }

      if (*best_point == nullptr)
        best_dist = edgept_dist (split_point, this_edgept);

      this_edgept =
        pick_close_point(split_point, this_edgept, &best_dist);
      if (this_edgept)
        *best_point = this_edgept;
    }

    p = p->next;
  }
  while (p != target_point);
}
Пример #3
0
/**********************************************************************
 * near_point
 *
 * Find the point on a line segment that is closest to a point not on
 * the line segment.  Return that point in near_pt.  Returns whether
 * near_pt was newly created.
 **********************************************************************/
bool Wordrec::near_point(EDGEPT *point,
                         EDGEPT *line_pt_0, EDGEPT *line_pt_1,
                         EDGEPT **near_pt) {
  TPOINT p;

  float slope;
  float intercept;

  float x0 = line_pt_0->pos.x;
  float x1 = line_pt_1->pos.x;
  float y0 = line_pt_0->pos.y;
  float y1 = line_pt_1->pos.y;

  if (x0 == x1) {
                                 /* Handle vertical line */
    p.x = (inT16) x0;
    p.y = point->pos.y;
  }
  else {
    /* Slope and intercept */
    slope = (y0 - y1) / (x0 - x1);
    intercept = y1 - x1 * slope;

    /* Find perpendicular */
    p.x = (inT16) ((point->pos.x + (point->pos.y - intercept) * slope) /
      (slope * slope + 1));
    p.y = (inT16) (slope * p.x + intercept);
  }

  if (is_on_line (p, line_pt_0->pos, line_pt_1->pos) &&
    (!same_point (p, line_pt_0->pos)) && (!same_point (p, line_pt_1->pos))) {
    /* Intersection on line */
    *near_pt = make_edgept(p.x, p.y, line_pt_1, line_pt_0);
    return true;
  } else {                           /* Intersection not on line */
    *near_pt = closest(point, line_pt_0, line_pt_1);
    return false;
  }
}
Пример #4
0
bool is_valid_rect() {
    int i, k;
    bool marked[4];
    for(i=0;i<4;i++) {
        if(lines[i].length_square == 0) {
            printf("length_square == 0\n");
            return false;
        }
        marked[i] = false;
    }
    rect.p[0].x = lines->p[0].x;
    rect.p[0].y = lines->p[0].y;
    rect.p[1].x = lines->p[1].x;
    rect.p[1].y = lines->p[1].y;
    marked[0] = true;
    bool found;
    for(i=2;i<4;i++) {
        found = false;
        for(k=0;k<4;k++) {
            if(!marked[k]) {
                if(same_point(lines[k].p, rect.p+i-1)) {
                    found = true;
                    rect.p[i].x = lines[k].p[1].x;
                    rect.p[i].y = lines[k].p[1].y;
                    marked[k] = true;
                    break;
                }
                else if(same_point(lines[k].p+1, rect.p+i-1)) {
                    found = true;
                    rect.p[i].x = lines[k].p[0].x;
                    rect.p[i].y = lines[k].p[0].y;
                    marked[k] = true;
                    break;
                }
            }
        }
        if(!found) {
            return false;
        }
    }
    for(i=0;i<4;i++)
        if(!marked[i]) {
            if(same_point(lines[i].p, rect.p)) {
                if(!(same_point(lines[i].p+1, rect.p+3)))
                    return false;
            }
            else if(same_point(lines[i].p+1, rect.p)) {
                if(!(same_point(lines[i].p, rect.p+3)))
                    return false;
            }
            else
                return false;
            break;
        }
    for(i=0;i<4;i++) {
        Point *a = i == 0 ? rect.p+3 : rect.p+i-1;
        Point *o = rect.p+i;
        Point *b = i == 4 ? rect.p : rect.p+i+1;
        if(!perpendicular(a, o, b))
            return false;
    }
    return true;
}
Пример #5
0
/*
 * We simplify the pattern recursively, using node "start" as a
 * "zipper" to zip the pattern up ("start" moves from left to
 * right as the recursion proceeds, and the recusion ends when
 * "start" reaches the end of the pattern).
 *
 * Overall strategy: We "check" whether we can remove "start" without
 * changing what ordinal the pointed pattern notates.  But if we remove
 * "start", we have to remove anything connected to it (via less1,
 * or via decompositions), so we have to ask the same question about
 * all those nodes as well, which in turn requires asking the same
 * question about any node THEY'RE connected to, and so on.
 */
static pattern *simplify_recurse( pattern *p, node *start )
{
  node *n;
  pattern *q;

  /*
   * Mark all nodes in the pattern as being unchecked during this iteration
   */
  for ( n = p->first_node; n; n = n->next )
    n->simplify_data = SIMPL_UNCHECKED;

  /*
   * Under no circumstances would we remove the pattern's designated point
   */
  if ( start == p->point )
  {
    start = start->next;
    if ( !start )
      return p;
  }

  /*
   * Attempt to mark "start" for removal.
   * If the attempt fails (because it would
   * require removing p->point) then move on
   * to the next start.
   */
  if ( ! mark_for_removal(p,start,start) )
  {
    if ( !start->next )
      return p;
    return simplify_recurse( p, start->next );
  }

  /*
   * If "start" was successfully marked for
   * removal, then remove it, along with anything
   * else that was marked as collateral damage.
   * Actually, do all this in a copy q of p.
   */
  q = execute_removal(p);

  /*
   * Check whether the copy q, with "start" removed,
   * still notates the same ordinal that p does.
   * If so, continue trying to further simplify q.
   * If not, revert back to p and increment "start".
   */
  if ( same_point(q,p) )
  {
    start = isom(start,q);

    if ( start )
      return simplify_recurse( q, start );
    else
      return q;
  }
  else
  {
    if ( start->next )
      return simplify_recurse( p, start->next );
    else
      return p;
  }
}
Пример #6
0
Файл: util.c Проект: wtok/snake
/* Move pt to a random, valid position within the
 * but it won't be on the map borders. */
inline Point
random_point_within_rect(Rect r)
{
	return (Point) { .x = r.x + (rand() % (r.w - 1)) + 1,
			 .y = r.y + (rand() % (r.h - 1)) + 1  };
}

/* Move given point one unit in the given direction. */
inline void
move_point(Point p[static 1], int direction)
{
	switch (direction) {
	case KEY_UP:    p->y -= 1; break;
	case KEY_LEFT:  p->x -= 1; break;
	case KEY_DOWN:  p->y += 1; break;
	case KEY_RIGHT: p->x += 1; break;
	}
}

/*** Snake utilities ***/

/* Is this point the snake? */
inline bool
point_is_snake(Point p, Snake s[static 1])
{
	for (size_t i = 0; i < s->length; ++i)
		if (same_point(p, s->history[i]))
			return true;
	return false;
}

/* Identical to above, but does not include the head. */
inline bool
point_is_tail(Point p, Snake s[static 1])
{
	for (size_t i = 1; i < s->length; ++i)
		if (same_point(p, s->history[i]))
			return true;
	return false;
}

/* Move all the snake's tail pieces up one place, then move its head one unit in
 * the given direction. */
void
move_snake(Snake s[static 1], int direction)
{
	for (size_t i = s->length; i > 0; --i)
		s->history[i] = s->history[i-1];
	move_point(&s->history[0], direction);
}

/* Will pathing to this point lose the game? */
inline bool
point_is_unpathable(Point p, Rect r, Snake s[static 1])
{
	return (!point_is_within_rect(p, r) || point_is_tail(p, s));
}

/*** Directions ***/

/* Is this integer a valid direction? */
inline bool
input_is_direction(int input)
{
	switch (input) {
	case KEY_LEFT:
	case KEY_UP:
	case KEY_RIGHT:
	case KEY_DOWN:
		return true;
	default:
		return false;
	}
}

/* Return the opposite direction of input */
inline int
opposite_direction(int direction)
{
	int opp = ERR;
	switch (direction) {
	case KEY_LEFT:  opp = KEY_RIGHT; break;
	case KEY_UP:    opp = KEY_DOWN;  break;
	case KEY_RIGHT: opp = KEY_LEFT;  break;
	case KEY_DOWN:  opp = KEY_UP;    break;
	}
	return opp;
}