Beispiel #1
0
void Sweep::FillBasinReq(SweepContext& tcx, Node* node)
{
  // if shallow stop filling
  if (IsShallow(tcx, *node)) {
    return;
  }

  Fill(tcx, *node);

  if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) {
    return;
  } else if (node->prev == tcx.basin.left_node) {
    Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point);
    if (o == CW) {
      return;
    }
    node = node->next;
  } else if (node->next == tcx.basin.right_node) {
    Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point);
    if (o == CCW) {
      return;
    }
    node = node->prev;
  } else {
    // Continue with the neighbor node with lowest Y value
    if (node->prev->point->y < node->next->point->y) {
      node = node->prev;
    } else {
      node = node->next;
    }
  }

  FillBasinReq(tcx, node);
}
Beispiel #2
0
void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point)
{
  if (IsEdgeSideOfTriangle(*triangle, ep, eq)) {
    return;
  }

  Point* p1 = triangle->PointCCW(point);
  Orientation o1 = Orient2d(eq, *p1, ep);
  if (o1 == COLLINEAR) {
	  // ASSIMP_CHANGE (aramis_acg)
	  throw std::runtime_error("EdgeEvent - collinear points not supported");
    if( triangle->Contains(&eq, p1)) {
      triangle->MarkConstrainedEdge(&eq, p1 );
      // We are modifying the constraint maybe it would be better to 
      // not change the given constraint and just keep a variable for the new constraint
      tcx.edge_event.constrained_edge->q = p1;
      triangle = &triangle->NeighborAcross(point);
      EdgeEvent( tcx, ep, *p1, triangle, *p1 );
    } else {
	  // ASSIMP_CHANGE (aramis_acg)
      std::runtime_error("EdgeEvent - collinear points not supported");
    }
    return;
  }

  Point* p2 = triangle->PointCW(point);
  Orientation o2 = Orient2d(eq, *p2, ep);
  if (o2 == COLLINEAR) {
	  // ASSIMP_CHANGE (aramis_acg)
	  throw std::runtime_error("EdgeEvent - collinear points not supported");

    if( triangle->Contains(&eq, p2)) {
      triangle->MarkConstrainedEdge(&eq, p2 );
      // We are modifying the constraint maybe it would be better to 
      // not change the given constraint and just keep a variable for the new constraint
      tcx.edge_event.constrained_edge->q = p2;
      triangle = &triangle->NeighborAcross(point);
      EdgeEvent( tcx, ep, *p2, triangle, *p2 );
    } else {
      // ASSIMP_CHANGE (aramis_acg)
      throw std::runtime_error("EdgeEvent - collinear points not supported");
    }
    return;
  }

  if (o1 == o2) {
    // Need to decide if we are rotating CW or CCW to get to a triangle
    // that will cross edge
    if (o1 == CW) {
      triangle = triangle->NeighborCCW(point);
    }       else{
      triangle = triangle->NeighborCW(point);
    }
    EdgeEvent(tcx, ep, eq, triangle, point);
  } else {
    // This triangle crosses constraint so lets flippin start!
    FlipEdgeEvent(tcx, ep, eq, triangle, point);
  }
}
Beispiel #3
0
void Sweep::FillBasin(SweepContext& tcx, Node& node)
{
  if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {
    tcx.basin.left_node = node.next->next;
  } else {
    tcx.basin.left_node = node.next;
  }

  // Find the bottom and right node
  tcx.basin.bottom_node = tcx.basin.left_node;
  while (tcx.basin.bottom_node->next
         && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) {
    tcx.basin.bottom_node = tcx.basin.bottom_node->next;
  }
  if (tcx.basin.bottom_node == tcx.basin.left_node) {
    // No valid basin
    return;
  }

  tcx.basin.right_node = tcx.basin.bottom_node;
  while (tcx.basin.right_node->next
         && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) {
    tcx.basin.right_node = tcx.basin.right_node->next;
  }
  if (tcx.basin.right_node == tcx.basin.bottom_node) {
    // No valid basins
    return;
  }

  tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x;
  tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y;

  FillBasinReq(tcx, tcx.basin.bottom_node);
}
Beispiel #4
0
void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
{
  Fill(tcx, *node.prev);
  if (node.prev->point != edge->p) {
    // Next above or below edge?
    if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) {
      // Below
      if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {
        // Next is concave
        FillLeftConcaveEdgeEvent(tcx, edge, node);
      } else{
        // Next is convex
      }
    }
  }

}
Beispiel #5
0
void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
{
  // Next concave or convex?
  if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) {
    // Concave
    FillLeftConcaveEdgeEvent(tcx, edge, *node.prev);
  } else{
    // Convex
    // Next above or below edge?
    if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) {
      // Below
      FillLeftConvexEdgeEvent(tcx, edge, *node.prev);
    } else{
      // Above
    }
  }
}
Beispiel #6
0
void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
{
  while (node->prev->point->x > edge->p->x) {
    // Check if next node is below the edge
    if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) {
      FillLeftBelowEdgeEvent(tcx, edge, *node);
    } else {
      node = node->prev;
    }
  }
}
Beispiel #7
0
Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
{
  Orientation o2d = Orient2d(eq, op, ep);
  if (o2d == CW) {
    // Right
    return *ot.PointCCW(op);
  } else if (o2d == CCW) {
    // Left
    return *ot.PointCW(op);
  } else{
    //throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
    assert(0);
  }
}
Beispiel #8
0
void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
{
  if (node.point->x > edge->p->x) {
    if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {
      // Concave
      FillLeftConcaveEdgeEvent(tcx, edge, node);
    } else {
      // Convex
      FillLeftConvexEdgeEvent(tcx, edge, node);
      // Retry this one
      FillLeftBelowEdgeEvent(tcx, edge, node);
    }
  }
}
Beispiel #9
0
Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
{
  Orientation o2d = Orient2d(eq, op, ep);
  if (o2d == CW) {
    // Right
    return *ot.PointCCW(op);
  } else if (o2d == CCW) {
    // Left
    return *ot.PointCW(op);
  } else{
    //throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
	  // ASSIMP_CHANGE (aramis_acg)
	  throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
  }
}
Beispiel #10
0
void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p)
{
  Triangle& ot = t->NeighborAcross(p);
  Point& op = *ot.OppositePoint(*t, p);

  if (&ot == NULL) {
    // If we want to integrate the fillEdgeEvent do it here
    // With current implementation we should never get here
    //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle");
    assert(0);
  }

  if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {
    // Lets rotate shared edge one vertex CW
    RotateTrianglePair(*t, p, ot, op);
    tcx.MapTriangleToNodes(*t);
    tcx.MapTriangleToNodes(ot);

    if (p == eq && op == ep) {
      if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) {
        t->MarkConstrainedEdge(&ep, &eq);
        ot.MarkConstrainedEdge(&ep, &eq);
        Legalize(tcx, *t);
        Legalize(tcx, ot);
      } else {
        // XXX: I think one of the triangles should be legalized here?
      }
    } else {
      Orientation o = Orient2d(eq, op, ep);
      t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op);
      FlipEdgeEvent(tcx, ep, eq, t, p);
    }
  } else {
    Point& newP = NextFlipPoint(ep, eq, ot, op);
    FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP);
    EdgeEvent(tcx, ep, eq, t, p);
  }
}