bool ribi::Geometry::IsCounterClockwise(const Doubles& angles) const noexcept
{
  const int sz = static_cast<int>(angles.size());
  assert(sz >= 2 && "Need at least two angles to determine if these are counter-clockwise");
  for (int i=0; i!=sz-1; ++i)
  {
    if (!IsCounterClockwise(angles[i],angles[i+1])) return false;
  }

  //Calculate cumulative clockwise distance
  const double tau{boost::math::constants::two_pi<double>()};
  double sum{0.0};
  for (int i=0; i!=sz-1; ++i)
  {
    const double diff{angles[i] - angles[i+1]}; //Order reversed compared to IsClockwise
    if (diff > 0.0)
    {
      sum += diff;
    }
    else
    {
      assert(diff + tau > 0.0);
      sum += (diff + tau);
    }
  }
  return sum < tau;
}
bool ribi::Geometry::IsCounterClockwiseCartesianHorizontal(const Coordinats2D& points) const noexcept
{
  //Points are determined from their center
  const auto center(CalcCenter(points));
  Doubles angles;
  angles.reserve(points.size());
  std::transform(points.begin(),points.end(),
    std::back_inserter(angles),
    [this,center](const Coordinat2D& coordinat)
    {
      return GetAngleClockCartesian(
        coordinat - center
      );
    }
  );
  return IsCounterClockwise(angles);
}
Beispiel #3
0
///
//Uses the Jarvis March algorithm to determine the smallest convex hull around
//a 2D set of points in the XY plane.
//
//Parameters:
//	hullList: The list to store all points on the hull
//	rigidBodies: The list of all pointmasses which we are forming the hull around
void JarvisMarch(std::vector<int> &hullList, const std::vector<RigidBody> &rigidBodies)
{
	//Step 1: Find the left-most point
	int pointOnHull = 0;
	int size = rigidBodies.size();
	for(int i = 1; i < size; i++)
	{
		if(rigidBodies[i].position.x < rigidBodies[pointOnHull].position.x) pointOnHull = i;
	}

	//Step 2: Create second variable to hold prospective points on the hull which can still be outruled
	int endPoint = 0;

	//Until we loop back around to the left-most point
	while(hullList.size() <= 0 || endPoint != hullList[0])
	{
		//Add the current point to the hull list
		hullList.push_back(pointOnHull);
		
		//Set the current prospective point as the first point
		endPoint = 0;

		for(int i = 1; i < size; i++)
		{
			//Construct an edge from the last point on the hull to the ith point
			glm::vec2 edge1 = glm::vec2(rigidBodies[i].position - rigidBodies[pointOnHull].position);
			//Construct an edge from the last point on the hull to the current prospective point
			glm::vec2 edge2 = glm::vec2(rigidBodies[endPoint].position - rigidBodies[pointOnHull].position);

			//If the edge to the ith point is counter clockwise with respect to the edge to the prospective point
			//Set the prospective point to the point at i
			if(endPoint == pointOnHull || IsCounterClockwise(edge1, edge2))
			{
				endPoint = i;
			}
		}

		//Set the point on hull
		pointOnHull = endPoint;
	}
}
ol::Collision ol::Shape::
LineStripCollision( const std_container1 &vertices, const std_container2 &otherVertices,
                    const Placement &thisPlacement, const Placement &otherPlacement,
                    bool getResults, bool thisConnectFirstAndLast, bool otherConnectFirstAndLast ) const {
   
   if( vertices.size() < 2 || otherVertices.size() < 2 ) {
      OlError( "An empty shape can't ever collide!" );
      return Collision( false );
   }
   
   Vec2D thisCo = thisPlacement.GetPosition();
   Vec2D otherCo = otherPlacement.GetPosition();
   
   Matrix2D thisTransform = thisPlacement.Get2DMatrix();
   Matrix2D otherTransform = otherPlacement.Get2DMatrix();
   
   typename std_container1::const_iterator thisIter = vertices.begin();
   
   const Vec2D rotationPivot = thisPlacement.GetRotationPivot();
   const Vec2D otherRotationPivot = otherPlacement.GetRotationPivot();
   
   Vec2D thisPrev = thisTransform.Transform( *thisIter - rotationPivot ) + thisCo + rotationPivot;
   
   thisIter++;
   
   std::vector< LinePair * > segmentLists;
   
   // Loop through each vertex //
   while( true ) {
      bool breakNow = false;
      
      // Test if we've reached the last line segment //
      if( thisIter == vertices.end() ) {
         if( !thisConnectFirstAndLast ) {
            break;
         }
         
         breakNow = true;
         thisIter = vertices.begin();
      }
      
      Vec2D thisVertex = thisTransform.Transform( *thisIter - rotationPivot ) + thisCo + rotationPivot;
      thisIter++;

      typename std_container2::const_iterator otherIter = otherVertices.begin();
      Vec2D otherPrev = otherTransform.Transform( *otherIter - otherRotationPivot ) + otherCo + otherRotationPivot;
      otherIter++;
      
      // Loop through each vertex of the other polygon //
      while( true ) {
         bool breakNow = false;
         
         // Test if we've reached the last line segment of the other polygon //
         if( otherIter == otherVertices.end() ) {
            if( !otherConnectFirstAndLast ) {
               break;
            }
            
            breakNow = true;
            otherIter = otherVertices.begin();
         }

         Vec2D otherVertex = otherTransform.Transform( *otherIter - otherRotationPivot )
                             + otherCo + otherRotationPivot;
         otherIter++;
         
         // Test for collision //
         if( IsCounterClockwise( thisPrev, thisVertex, otherPrev )
             != IsCounterClockwise( thisPrev, thisVertex, otherVertex )
             &&
             IsCounterClockwise( otherPrev, otherVertex, thisPrev )
             != IsCounterClockwise( otherPrev, otherVertex, thisVertex )) {
            
            if( !getResults ) {
               return Collision( true );
            }
            else {
               Line thisLine( thisVertex, thisPrev );
               Line otherLine( otherVertex, otherPrev );
               
               segmentLists.push_back( new LinePair( thisLine, otherLine ));
               
               /*
               return Collision( thisLine, otherLine );*/
            }
         }

         // Is last line segment of the other polygon processed? //
         if( breakNow ) {
            break;
         }

         // Advance to the next vertex of the other polygon //
         otherPrev = otherVertex;
      }

      // Is last line segment processed? //
      if( breakNow ) {
         break;
      }

      // Advance to the next vertex //
      thisPrev = thisVertex;
   }
   
   if( !segmentLists.empty() ) {
      return Collision( segmentLists );
   }
   
   return Collision( false );
}