Exemplo n.º 1
0
void SpriteTests::testTrickyIntersections()
{
  AutoreleasePool::begin();
  Sprite* space_ship = new Sprite(new MockView);
  space_ship->setPosition(Vector2(0.0f, 0.0f));
  // Obstacle
  Polygon2 points;
  points.push_back(Vector2(36.714285714286f, 29.857142857143f));
  points.push_back(Vector2(40.285714285714f,	29.714285714286f));
  points.push_back(Vector2(40.142857142857f,	1.0f));
  points.push_back(Vector2(30.0f, 0.85714285714286f));
  points.push_back(Vector2(30.428571428571f, 13.285714285714f));
  
  Sprite* obstacle = new Sprite(new MockView(points));
        
  CPTAssert(!space_ship->collide(obstacle, t, dt));    
  CPTAssert(!obstacle->collide(space_ship, t, dt));    
    
  space_ship->setPosition(Vector2(9.7f, -2.7f));  

  CPTAssert(!space_ship->collide(obstacle, t, dt));    
  CPTAssert(!obstacle->collide(space_ship, t, dt));    


  space_ship->setPosition(Vector2(11.9f, 7.71f));  

  CPTAssert(!space_ship->collide(obstacle, t, dt));    
  CPTAssert(!obstacle->collide(space_ship, t, dt));    


  space_ship->setPosition(Vector2(11.99f, 7.89f));  

  CPTAssert(!space_ship->collide(obstacle, t, dt));    
  CPTAssert(!obstacle->collide(space_ship, t, dt));    

  Group* g = new Group;
  g->addKid(obstacle);
  ShapeGroup* group = new ShapeGroup(g->iterator());
  
  CPTAssert(!space_ship->collide(group, t, dt));      
  CPTAssert(!group->collide(space_ship, t, dt));      


  space_ship->setPosition(Vector2(9.7f, -2.7f));  

  CPTAssert(!space_ship->collide(group, t, dt));    
  CPTAssert(!group->collide(space_ship, t, dt));    
      
      
  space_ship->setPosition(Vector2(11.9f, 7.71f));  

  CPTAssert(!space_ship->collide(group, t, dt));    
  CPTAssert(!group->collide(space_ship, t, dt)); 
        
  g->release();
  group->release();
  space_ship->release();  
  obstacle->release();    
  AutoreleasePool::end();  
}
Exemplo n.º 2
0
static bool pathFrom(const Graph& g, Vertex t, const Vertices& p, Polygon2& path)
{
  while (t != p[t]) {
    path.push_back(g[t]);
    t = p[t];
  }
  path.push_back(g[t]);  
  return true;
}
Exemplo n.º 3
0
    TEST_CASE_F(ComputePolygonOrientation_GivenLowestLeftmostTriangleIsDegenerate_ReturnsCorrectOrientation, Fixture)
    {
        Polygon2 polygon;
        polygon.push_back(Vector2Type(0.0, 1.0));
        polygon.push_back(Vector2Type(1.0, 1.0));
        polygon.push_back(Vector2Type(0.0, 0.0));
        polygon.push_back(Vector2Type(0.0, 0.0));

        TriangulatorType triangulator;
        const TriangulatorType::Orientation orientation =
            triangulator.compute_polygon_orientation(polygon);

        EXPECT_EQ(TriangulatorType::CW, orientation);
    }
Exemplo n.º 4
0
/*!
  The collision polygon calculated isn't optimal. We do it because it is used
  for drawing. For collision handling it is poor.
  
  \todo Refactor so collision and drawing polygon don't need to be the same
*/
PointsView::PointsView(Points2::iterator begin, Points2::iterator end) : iPoints(begin, end)
{
  // Find rectangular polygon that will enclose all
  // added points
  Rect2 r;
  Points2::iterator it;
  for (it = begin; it != end; ++it) {
    r = r.surround(*it);
  }
  
  Polygon2 p;
  p.push_back(r.bottomLeft());
  p.push_back(r.bottomRight());
  p.push_back(r.topRight());
  p.push_back(r.topLeft());      
  
  setCollisionPolygon(p);
}
Exemplo n.º 5
0
/*! 
  Gets polygon from array of points stored at index t in 
  lua stack. We assume array is a table of the form
  {{x = 1, y = 2}, {x = 3, y = 4}}. Polygon is returned in p. 
*/
void getPolygon(lua_State* L, int t, Polygon2& p) 
{
  luaL_checktype(L, t, LUA_TTABLE); // Make sure we get a table with points as first argument
  lua_pushnil(L); // first key (ready traversal of table)
  while (lua_next(L, t) != 0) { 
    // ‘key’ is at index -2 and ‘value’ at index -1 
    p.push_back(Vector2_pull(L,-1));
    lua_pop(L, 1); // removes ‘value’; keeps ‘key’ for next iteration   
  }
}
Exemplo n.º 6
0
bool GraphImp2::shortestPath(Trapezoid2* source, Trapezoid2* target, Polygon2& path) const
{
  assert(iGraph != 0);
  assert(source != 0 && target != 0);
  Graph& g = *iGraph;

  // Find source and target vertex in graph
  Vertex s = vertex(source->tag(), g);
  Vertex t = vertex(target->tag(), g);
  
  Vertices p(num_vertices(g));  // Predecessor map
  Reals    d(num_vertices(g));  // Distance map
  
  // A* will find ALL shortest paths like Dijkstra so we need to throw exception when goal has been found
  try {
    astar_search(
      g, 
      s,
      DistanceHeuristic(iGraph, t),
      weight_map(get(&EdgeProperty::weight, g)).
      predecessor_map(make_iterator_property_map(p.begin(), get(vertex_index, g))).
      distance_map(make_iterator_property_map(d.begin(), get(vertex_index, g))).
      visitor(GoalVisitor(t))
    );    
  }
  catch (FoundGoalException e) {
    Vertex t = vertex(target->tag(), g);
    
    // Store coordinates of shortest path
    while (t != p[t]) {
      path.push_back(g[t]);
      t = p[t];
    }
    path.push_back(g[t]);    
    reverse(path.begin(), path.end());
    
    return true;
  }
  
  return false;
}
Exemplo n.º 7
0
/**
 * This was indentified as a trouble area. Numbers were produced from
 * recording points which caused trouble in simulator.
 */
void SpriteTests::testSpecialIntersect()
{
  AutoreleasePool::begin();
  Polygon2 ship_points;
  ship_points.push_back(Vector2(8.59, -3.69));
  ship_points.push_back(Vector2(10.59, -2.69));
  ship_points.push_back(Vector2(8.59, -1.69));
   
  MockView* view = new MockView(ship_points);
  Sprite* space_ship = new Sprite(view);
  space_ship->setPosition(Vector2(0.0f, 0.0f));
  
  // Obstacle
  Polygon2 points;
//  points.push_back(Vector2(16.7143, 9.85714));
//  points.push_back(Vector2(20.2857, 9.71429));
//  points.push_back(Vector2(20.1429, -19));
//  points.push_back(Vector2(10, -19.1429));
//  points.push_back(Vector2(10.4286, -6.71429));

  points.push_back(Vector2(10.4286, -6.71429));
  points.push_back(Vector2(10, -19.1429));
  points.push_back(Vector2(20.1429, -19));
  points.push_back(Vector2(20.2857, 9.71429));        
  points.push_back(Vector2(16.7143, 9.85714));

  Sprite* obstacle = new Sprite(new MockView(points));
  obstacle->setPosition(Vector2(0.0f, 0.0f));
        
  CPTAssert(!space_ship->collide(obstacle, t, dt));    
  CPTAssert(!obstacle->collide(space_ship, t, dt));    
    
  space_ship->release();  
  obstacle->release(); 
  AutoreleasePool::end();  
}
Exemplo n.º 8
0
bool	build_convex_polygon(
				Pmwx::Ccb_halfedge_circulator									ccb,
				vector<pair<Pmwx::Halfedge_handle, Pmwx::Halfedge_handle> >&	sides,
				const CoordTranslator2&											trans,
				Polygon2&														metric_bounds,
				double															max_err_mtrs,
				double															min_side_len)
{
	double	e_sq = max_err_mtrs*max_err_mtrs;
	sides.clear();
	metric_bounds.clear();
	
	Pmwx::Ccb_halfedge_circulator circ(ccb);
//	Bbox2				bounds;
//	
//	do {
//		bounds += cgal2ben(circ->source()->point());
//	} while (++circ != ccb);

	Pmwx::Ccb_halfedge_circulator start,next;
	start = ccb;
	do {
		--start;
		if(!sides_can_merge(start,ccb))
			break;
		if(!within_err_metric(start,ccb,trans,e_sq))
			break;		
	} while(start != ccb);
	++start;
	
	// now we can go around.

	circ = start;
	//int ne = count_circulator(start);
	//printf("Poly has %d sides.\n", ne);
	do {
	 
		Pmwx::Ccb_halfedge_circulator stop(circ);
		do {
			++stop;
		} while(sides_can_merge(circ,stop) && within_err_metric(circ,stop,trans,e_sq) && stop != start);
	
		--stop;
		//printf("Pushing side of %d, %d\n", circulator_distance_to(start, circ),circulator_distance_to(start,stop));
		sides.push_back(pair<Pmwx::Halfedge_handle,Pmwx::Halfedge_handle>(circ, stop));
		++stop;
		circ = stop;
	
	} while(circ != start);
	
	if(sides.size() < 3)	
	{
		//debug_mesh_point(bounds.centroid(),1,1,1);
		return false;
	}
	
	int i, j, k;
	
	vector<Segment2>	msides;
	for(i = 0; i < sides.size(); ++i)
	{
		j = (i + 1) % sides.size();		
		DebugAssert(sides[i].second->target() == sides[j].first->source());
		msides.push_back(Segment2(
						trans.Forward(cgal2ben(sides[i].first->source()->point())),
						trans.Forward(cgal2ben(sides[i].second->target()->point()))));						
	}	
	vector<Segment2>	debug(msides);
	for(i = 0; i < sides.size(); ++i)
	{
		j = (i + 1) % sides.size();		
		Vector2	v1(msides[i].p1,msides[i].p2);
		Vector2	v2(msides[j].p1,msides[j].p2);
		v1.normalize();
		v2.normalize();
		if(v1.dot(v2) > 0.9998 ||
			!v1.left_turn(v2))
		{
			//debug_mesh_point(trans.Reverse(msides[i].p2),1,0,0);
			return false;
		}
		double w = width_for_he(sides[i].first);
		if(w)
		{
			v1 = v1.perpendicular_ccw();
			v1 *= w;
			msides[i].p1 += v1;
			msides[i].p2 += v1;
		}
	}
	for(j = 0; j < sides.size(); ++j)
	{
		i = (j + sides.size() - 1) % sides.size();
		Line2 li(msides[i]), lj(msides[j]);
		Point2	p;
		if(!li.intersect(lj,p))
		{
			Assert(!"Failure to intersect.\n");
			return false;
		}
		metric_bounds.push_back(p);
	}
	
	for(i = 0; i < metric_bounds.size(); ++i)
	{
		j = (i + 1) % metric_bounds.size();
		k = (i + 2) % metric_bounds.size();
		if(metric_bounds.side(i).squared_length() < (min_side_len*min_side_len))
		{
			//debug_mesh_line(trans.Reverse(metric_bounds.side(i).p1),trans.Reverse(metric_bounds.side(i).p2),1,1,0,1,1,0);
			return false;
		}
		if(!left_turn(metric_bounds[i],metric_bounds[j],metric_bounds[k]))
		{
			//debug_mesh_point(trans.Reverse(metric_bounds[j]),1,1,0);
			return false;
		}
		if(Vector2(msides[i].p1,msides[i].p2).dot(Vector2(metric_bounds[i],metric_bounds[j])) < 0.0)
		{
			//debug_mesh_line(trans.Reverse(msides[i].p1),trans.Reverse(msides[i].p2),1,0,0,1,0,0);
			return false;
		}
	}
	DebugAssert(metric_bounds.size() == msides.size());
	DebugAssert(msides.size() == sides.size());
		
	return true;
}
Exemplo n.º 9
0
bool GraphImp2::fixedLengthPath(Trapezoid2* source, Trapezoid2* target, real distance, Polygon2& path) const
{
  assert(iGraph != 0);
  assert(source != 0);
  Graph& g = *iGraph;

  // Variables for book keeping
  Vertex vs, vc;  // 'vertex selected' and 'vertex candidate'
  Vertex s, t;    // source vertex and target vertex
  Edge es, ec;    //  'edge selected' and 'edge candidate'
  real ds, dc;        // 'distance selected'
  
  vs = s = vertex(source->tag(), g);
  t = vertex(target->tag(), g);

  Vertices  p(num_vertices(g));
  Reals     d(num_vertices(g));  
  
  dijkstra(g, t, p, d);

  // Check if the shortest path has the desired length or is too long
  real cur_dist = d[s];
  real accum_dist = 0.0;
  
  if (cur_dist > distance)
    return false;
  if (cur_dist == distance) {
    return pathFrom(g, s, p, path);
  }
  
  OutEdgeIterator ei, ee, selected;
  while (vs != t) {
    // For each selected vertex iterate over out edges to determine next vertex in path
    tie(ei, ee) = out_edges(vs, g);
    es = *ei;      //  'es' is temporary selected next edge
    vs = ::target(es, g);  // 'vs' is temporary selected as next vertex
    
    // distance to to target through temporary selected vertex 'vs'
    ds = g[es].weight+accum_dist+d[vs];    
    
    // Loop through all neighbor vertices to last selected vertex and find
    // the vertex that will increase the distance of the path but still
    // keep it below the max distance 'distance'
    for (++ei; ei != ee; ++ei) {
      ec = *ei;           // 'ec' is candidate for selected edge
      vc = ::target(ec, g); // 'vc' is candidate for selected vertex

      // distance to target through candidate vertex 'vc'
      dc = g[ec].weight+accum_dist+d[vc];

      // Only select candidate vertex 'vc' if it can increase distance to target
      // but still be less than max distance.
      if (dc < ds || dc > distance) 
        continue;

      // Make candidate vertex the selected vertex
      ds = dc;
      es = ec;
      vs = vc;      
    }
    path.push_back(g[vs]);  
  }

  return true;
}
Exemplo n.º 10
0
    bool isGood() {
        stringstream ss;
        ss << points.size() << endl;

        auto out = [&](const Gmpq& q) {
            if (1 != q.denominator()) {
                ss << q;
            } else {
                ss << q.numerator();
            }
        };

        vector<Point2> vp(points.size());
        for (const auto& p: points) {
            vp[p.second] = p.first;
        }

        for (const auto& p: vp) {
            out(p.x());
            ss << ",";
            out(p.y());
            ss << endl;
        }
        ss << facets.size() << endl;
        map<Point2, Point2> transform;
        for (const auto& f: facets) {
            ss << f.polygon.size();
            Polygon2 transformed;
            auto inverse = f.transformation.inverse();
            for (auto fp = f.polygon.vertices_begin(); fp != f.polygon.vertices_end(); ++fp) {
                auto inv = inverse(*fp);
                if (0 == points.count(inv)) {
                    cout << "point not found" << endl;
                    return false;
                }
                ss << " " << points[inv];
                transformed.push_back(vp[points[inv]]);
                transform[inv] = *fp;
            }
            ss << endl;
            auto area = transformed.area();
            if (0 == area) {
                cout << "empty facet" << endl;
                return false;
            }
            if (abs(area) != abs(f.polygon.area())) {
                cout << "not congruent" << endl;
                return false;
            }
        }
        for (const auto& p: vp) {
            if (!transform.count(p)) {
                cout << "point not found 2" << endl;
                return false;
            }
            auto transformed = transform[p];
            out(transformed.x());
            ss << ",";
            out(transformed.y());
            ss << endl;
        }
        sSolution = ss.str();
        // cout << sSolution << endl;
        return sSolution.size() < 5000;
    }
Exemplo n.º 11
0
    Solution split(const Line2& line, bool up) const {
        Solution result;
        result.points = points;
        for (const auto& facet: facets) {
            if (doIntersect(facet.polygon, line)) {
                Facet facet1;
                facet1.transformation = facet.transformation;
                Facet facet2;
                Transformation2 reflection( sqr(line.b()) - sqr(line.a()), -2*line.a()*line.b(), -2*line.a()*line.c(),
                                            -2*line.a()*line.b(), sqr(line.a()) - sqr(line.b()), -2*line.b()*line.c(),
                                            sqr(line.a()) + sqr(line.b()) );
                facet2.transformation = reflection*facet.transformation;
                auto inverse = facet.transformation.inverse();
                bool fail = false;
                for (auto edge = facet.polygon.edges_begin(); edge != facet.polygon.edges_end(); ++edge) {
                    const auto len2 = edge->squared_length();
                    const auto len2new = edge->transform(facet2.transformation).squared_length();
                    if (len2 != len2new) {
                        throw runtime_error("bad transform");
                    }

                    if (line.has_on_positive_side(edge->source()) == up) {
                        facet1.polygon.push_back(edge->source());
                    } else {
                        facet2.polygon.push_back(reflection(edge->source()));
                    }
                    auto intersect = intersection(*edge, line);
                    if (intersect) {
                        Point2* p = boost::get<Point2>(&*intersect);
                        if (p) {
                            auto revPoint = inverse(*p);
                            if (!result.points.count(revPoint)) {
                                result.points[revPoint] = result.points.size();
                            }
                            facet1.polygon.push_back(*p);
                            facet2.polygon.push_back(*p);
                        } else {
                            fail = true;
                        }
                    }
                }
                auto normalize = [&](Facet& f) {
                    auto area = f.polygon.area();
                    if (area == 0) {
                        return;
                    }
                    vector<Point2> points(f.polygon.size());
                    for (size_t i = 0; i < f.polygon.size(); ++i) {
                        points[i] = f.polygon[i];
                    }
                    points.erase(unique(points.begin(), points.end()), points.end());
                    if (points.empty()) {
                        return;
                    }
                    if (area < 0) {
                        reverse(points.begin(), points.end());
                    }
                    Polygon2 p;
                    for (const auto& pnt: points) {
                        p.push_back(pnt);
                    }
                    f.polygon = p;
                    result.facets.push_back(f);
                };
                if (!fail) {
                    normalize(facet1);
                    normalize(facet2);
                } else {
                    result.facets.push_back(facet);
                }
            } else {
                result.facets.push_back(facet);
            }
        }

        for (const auto& f: result.facets) {
            result.polygon.join(f.polygon);
        }

        return result;
    }