I've recently found code on stackoverflow, that is used to handle collision beteween polygon and circle and it works. The problem is beacause I do not quite understand it so I would be greatful if somebody could provide me simple explanation.
// Check if Polygon intersects Circle
private boolean isCollision(Polygon p, Circle c) {
float[] vertices = p.getTransformedVertices();
Vector2 center = new Vector2(c.x, c.y);
float squareRadius = c.radius * c.radius;
for (int i = 0; i < vertices.length; i += 2) {
if (i == 0) {
if (Intersector.intersectSegmentCircle(new Vector2(
vertices[vertices.length - 2],
vertices[vertices.length - 1]), new Vector2(
vertices[i], vertices[i + 1]), center, squareRadius))
return true;
} else {
if (Intersector.intersectSegmentCircle(new Vector2(
vertices[i - 2], vertices[i - 1]), new Vector2(
vertices[i], vertices[i + 1]), center, squareRadius))
return true;
}
}
return false;
}
The part that I do not get it is the for loop.
intersectSegmentCircle effectively takes a line segment (as specified by the first two vector arguments), and a circle (as specified by the last vector and float arguments), and returns true if the line intersects the circle.
The for loop is looping through the vertices of the polygon (incrementing by two since a vertex is represented by two values in float[] vertices). For each vertex in turn, it considers the line segment formed by joining that vertex to the previous one in the polygon (i.e. it considers each edge of the polygon in turn).
If intersectSegmentCircle finds a circle intersection for that segment, the method returns true. If no intersections are found by the end it returns false.
The if/else in the for loop is just for the first vertex - the 'previous' vertex in this case will actually be the last one in float[] vertices, since a polygon loops round and joins the last vertex back to the first.
Related
Point 1, say it is (0, 0) and I have another point that should turn around at a distance of 10f. Then I'll adding degrees angle to make it rotate. I be wanting to know how to calculate that point that this turning around each other ..
I will use the raycasting, I need to rotate the ray (clockwise) to detect collisions
So you say you have point1 and point2, both separated by a distance of 10f where point2 will be rotating around point1, and you want to know if between this separation an object at some point is intersecting them, something like the following image:
There are tutorials to get the maths for rotate a point arount another one in internet, like this one, and since you can't specify an origin for a Vector2, a translated version of the code proposed in the previews link to java should be something similar to:
public Vector2 rotatePoint(Vector2 center, Vector2 point, float angle) {
angle = angle * MathUtils.degreesToRadians; // Convert to radians
float rotatedX = MathUtils.cos(angle) * (point.x - center.x)
- MathUtils.sin(angle) * (point.y - center.y) + center.x;
float rotatedY = MathUtils.sin(angle) * (point.x - center.x)
+ MathUtils.cos(angle) * (point.y - center.y) + center.y;
// rotated new position:
return new Vector2(rotatedX, rotatedY);
}
As for the rest of the code (the intersection between objects), I guess you are looking for the RayCastCallback interface:
// initial position
Vector2 point1 = new Vector(0, 0);
// Max lenght of view
Vector2 point2 = new Vector(0, 10);
// Position of collision if occur
final Vector2 collisionPoint = new Vector();
#Override
public void render(float delta) {
//...
point2 = rotatePoint(point1, point2, 10); // rotate 10ยบ
// to detect if object at position point1 is seeing something
world.rayCast(new RayCastCallback(){
#Override
public float reportRayFixture(Fixture fixture, Vector2 point,
Vector2 normal, float fraction) {
// what do the object saw? -> fixture
// where do the object saw it? -> point
collisionPoint.set(point);
return 0; // <- return 0 to stop raycasting
}
}, point1, point2);
//... rotation and other stuffs...
}
The return parameter of reportRayFixture have this documentation:
Called for each fixture found in the query. You control how the ray cast proceeds by returning a float: return -1: ignore this fixture and continue return 0: terminate the ray cast return fraction: clip the ray to this point return 1: don't clip the ray and continue. The Vector2 instances passed to the callback will be reused for future calls so make a copy of them!
** Emphasis added.
Basically it says that you can check for all the intersections one by one, but if you care only for the first one, return 0 immediately. This is useful when you want to know if an object is being blocked by another one. In this case, I return 0 and copy the value of point to collisionPoint to let you do whatever you want to do with this value.
A very nice example can be found in this video.
Hope you find this useful.
You should consider using Intersector class to check if the line from your actor intersects with the body shape.
To calculate end of "sight" line use Vector2 that you will be rotating according to your actor rotation (which is actually answer for your question)
It should looks like:
Vector2 sightVector = new Vector2(10f, 0); //the 10f is actually your sight max distance
sightVector.rotate(actor.getRotation());
...
#Override
pblic void render(float delta) //it can be also act of the actor
{
sightVector.rotate(actor.getRotation());
Vector2 endOfLine = new Vector2(actor.getX() + sightVector.x, actor.getY() + sightVector.y); //here you are calculating the end of line
Polygon bodyShape = getBodyShape( theBody ); //you should create a method that will return your body shape
if( Intersector.intersectLinePolygon(new Vector2(actor.getX(), actor.getY()), endOfLine, bodyShape) )
{
//do something
}
...
}
Intersector has method to check intersection with circles etc also so your body Shape doesn't need to be polygon
i have polygon say (Hexagonal with 6 lines) this Hexagonal connected from center with 6 point That make 6 triangles
I need when move any point(cause to move triangles) ,, other points move like this point i mean if the left point move to lift other points move to the left and so on
the code I want like this ptcP1.x and ptcP1.y the point that i moving it other point move depend on ptcP1 movement note that, this equations work fine in square shape ,, put in Penta and hexa ..etc this equations in valid so can any one help me
function button1_triggeredHandler( event:Event ):void
{
mode="mode2";
//trace(list.selectedIndex);
if(list.selectedIndex==1)
{
DrawSqure.ptcP1.x = Math.random() + 50;
DrawSqure.ptcP1.y = Math.random() + 50;
DrawSqure.ptcP2.y = 50-DrawSqure.ptcP1.x;
DrawSqure.ptcP2.x = DrawSqure.ptcP1.y;
DrawSqure.ptcP3.x = 50-DrawSqure.ptcP1.y;
DrawSqure.ptcP3.y = DrawSqure.ptcP1.x;
DrawSqure.ptcP4.x = 50-DrawSqure.ptcP1.x;
DrawSqure.ptcP4.y = 50-DrawSqure.ptcP1.y;
}
As stated in the comments, storing the vertices/points into a container (Array or Vector) and then adjusting those positions when you move is the best way to do it. Here is an example of how that might work:
//setup array or vector of vertices
var polygonVertices:Array = [DrawPolygon.ptcP1, DrawPolygon.ptcP2, DrawPolygon.ptcP3, DrawPolygon.ptcP4];
This method will take all the vertices and apply the translation:
//function for adjusting all the vertices based on the distance you pass
function moveShape( vertices:Array, dx:Number, dy:Number ) {
var i:int;
for ( ; i < vertices.length; i++ ) {
vertices[i].x += dx;
vertices[i].y += dy;
}
}
Then you would just need to know your distance X & Y your shape has moved and you can call moveShape( polygonVertices, 100, 100 );
I inserted 100,100 as the distance parameters as an example, but this should give you the results you are looking for.
ok so i have a character called character_mc and i want it to move towards the mouse when you press the forward arrow and strafe relative to right angles of that.
i am quite new to actionscript so could you please include and example of your code in my original code
Here is my current code:
import flash.events.MouseEvent;
//Event Listners
stage.addChild(crosshair_mc);
crosshair_mc.mouseEnabled = false;
crosshair_mc.addEventListener(Event.ENTER_FRAME, fl_CustomMouseCursor);
function fl_CustomMouseCursor(event:Event)
{
crosshair_mc.x = stage.mouseX;
crosshair_mc.y = stage.mouseY;
}
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,facecursor);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_KeyboardDownHandler);
//Functions
function facecursor(event):void
{
character_mc.rotation = (180 * Math.atan2(mouseY - character_mc.y,mouseX - character_mc.x))/Math.PI + 90;
}
function fl_KeyboardDownHandler(event:KeyboardEvent):void
{
trace("Key Code Pressed: " + event.keyCode);
if (event.keyCode == 38)
{
character_mc.y = character_mc.y - 5;
}
if (event.keyCode == 40)
{
character_mc.y = character_mc.y + 5;
}
if (event.keyCode == 39)
{
character_mc.x = character_mc.x + 5;
}
if (event.keyCode == 37)
{
character_mc.x = character_mc.x - 5;
}
}
I can tell you the basic concept of how you could do this, but you'll have to apply it to your own code. To involves converting your movement code to use a vector, then modifying the vector to get a direction facing the mouse (or at right angles to that direction) and a little bit of math.
Right now you have the character moving straight along the x and y axis only in each key press case. Left/Right only move along the X and Up/Down only move along the Y.
To move towards the mouse will require the character to move both along the X and Y when the Up/Down/Left/Right keys are pressed. Clearly you can see if you move both the character's x/y positions by the same amount, say 5, then it'll move exactly at 45 degrees (though it'll actually move a step of 7.07 pixels, hopefully you can see why). You can represent this as a vector: (5,5). You can use a Point object to represent this vector:
var movementVector:Point = new Point(5, 5);
trace(movementVector.x); // gives 5
trace(movementVector.y); // also gives 5
With that in mind, you can also use a vector to represent movement straight up and down on the y axis:
// set the x to 0 and y to 5
movementVector.x = 0; // 0 would mean not to move the character along the x
movementVector.y = 5; // using -5 would move the character up
And to move along the x axis only:
movementVector.x = 5; // using -5 would move the character right
movementVector.y = 0; // 0 would mean not to move the character along the y
To do the actual movement of the character would be the same as you are doing now, except you use the vector's values:
character_mc.x = character_mc.x + movementVector.x;
character_mc.y = character_mc.y + movementVector.y;
Now to figure out the proper vector to move on a diagonal from the character's position to the mouse position is pretty simple. The x value of the vector is the x distance from the character to the mouse, and the y value of the vector is the y distance from the character to the mouse.
Let's say the character is ay 125, 100 and the mouse at 225, 150. This means the distance between the character and mouse is 100, 50 x and y. Thus you'd end up with a vector:
movementVector.x = 100;
movementVector.y = 50;
If you were to apply this vector as it is to the character's position as it is, it would arrive at the mouse instantly (and then go beyond it) as the character is moving 100 pixels along the x and 50 pixels along the y right away. The step size would be 111.8 pixels long -too big. You would need to scale it down to the character's speed. You can do this by calling the normalise() method on the Point class to scale down the vector:
trace(movementVector.x); // gives 100
trace(movementVector.y); // gives 50
// assuming '5' is the max speed of the character
movementVector.normalise(5);
trace(movementVector.x); // gives 4.47213595499958
trace(movementVector.y); // gives 2.23606797749979
This would result in a 'step' size of 5 now. Applying this would make your character move 5 pixels towards a point 100 pixels to the right and 50 pixels down from where it started.
To transform a vector exactly 90 degrees, a quick and simple way is to swap the x and y values around.
If you are curious on what normalise() method mathematically does, is that it takes the x and y values of the vector (or point) and divides it by the length to get a unit vector (or a vector with a step size of 1), then times the input you give it to scale it to the desired length.
To move your character_mc towards the mouse point you only need the direction vector between the two:
var dir:Point = new Point(mouseX - character_mc.x, mouseY - character_mc.y);
dir.Normalize();
// The following should be called when the 'up' or 'forward' arrow is pressed
// to move the character closer to mouse point
character_mc.x += dir.x; // dir can be multiplied by a 'speed' variable
character_mc.y += dir.y;
Strafing left and right around the point is a little more tricky:
// Where radius is the distance between the character and the mouse
character_mc.x = mouseX + radius * Math.cos(rad);
character_mc.y = mouseY + radius * Math.sin(rad);
You should find this tutorial useful as it does everything you describe and more:
http://active.tutsplus.com/tutorials/actionscript/circular-motion-in-as3-make-one-moving-object-orbit-another/
I have a single triangle and a plane (in 3 dimensional space), How would I calculate the line segment where the two cross, if there is no crossing then I need to detect this case.
The end result I'm looking for is two 3 dimensional vectors, which define the start and end points of the line segment.
To help you out a little, I have already calculated the intersection ray between the plane of the face, and the plane, I simply need to find the endpoints to clip that ray into a line segment.
For those who like reading things in code:
Face face; //a face, defined by 3 points
Plane plane; //a plane, defined by a normal vector and a distance
Ray intersection; //a ray, defined by a point and a direction, initialised to the intersection of the face plane and the face
Segment s = CalculateSegment(face, plane, intersection); //this method needs defining
Here's some suggested pseudo code. Simple version first, more robust version later (just to help separate the principle from the neuances).
Simple version:
// Assume the plane is given as the equation dot(N,X) + d = 0, where N is a (not
// neccessarily normalized) plane normal, and d is a scalar. Any way the plane is given -
// DistFromPlane should just let the input vector into the plane equation.
vector3d planeN;
float planeD;
float DistFromPlane( vector3d P)
{
// if N is not normalized this is *not* really the distance,
// but the computations work just the same.
return dot(planeN,P) + planeD;
}
bool GetSegmentPlaneIntersection( vector3d P1, vector3d P2, vector3d& outP)
{
float d1 = DistFromPlane(P1),
d2 = DistFromPlane(P2);
if (d1*d2 > 0) // points on the same side of plane
return false;
float t = d1 / (d1 - d2); // 'time' of intersection point on the segment
outP = P1 + t * (P2 - P1);
return true;
}
void TrianglePlaneIntersection(vector3d triA, vector3d triB, vector3d triC,
vector3dArray& outSegTips)
{
vector3d IntersectionPoint;
if( GetSegmentPlaneIntersection( triA, triB, IntersectionPoint))
outSegTips.Add(IntersectionPoint);
if( GetSegmentPlaneIntersection( triB, triC, IntersectionPoint))
outSegTips.Add(IntersectionPoint);
if( GetSegmentPlaneIntersection( triC, triA, IntersectionPoint))
outSegTips.Add(IntersectionPoint);
}
Now adding some robustness:
[Edit: Added explicit consideration for the case of a single vertex on the plane]
vector3d planeN;
float planeD;
float DistFromPlane( vector3d P)
{
return dot(planeN,P) + planeD;
}
void GetSegmentPlaneIntersection( vector3d P1, vector3d P2, vector3dArray& outSegTips)
{
float d1 = DistFromPlane(P1),
d2 = DistFromPlane(P2);
bool bP1OnPlane = (abs(d1) < eps),
bP2OnPlane = (abs(d2) < eps);
if (bP1OnPlane)
outSegTips.Add(P1);
if (bP2OnPlane)
outSegTips.Add(P2);
if (bP1OnPlane && bP2OnPlane)
return;
if (d1*d2 > eps) // points on the same side of plane
return;
float t = d1 / (d1 - d2); // 'time' of intersection point on the segment
outSegTips.Add( P1 + t * (P2 - P1) );
}
void TrianglePlaneIntersection(vector3d triA, vector3d triB, vector3d triC,
vector3dArray& outSegTips)
{
GetSegmentPlaneIntersection( triA, triB, outSegTips));
GetSegmentPlaneIntersection( triB, triC, outSegTips));
GetSegmentPlaneIntersection( triC, triA, outSegTips));
RemoveDuplicates(outSegTips); // not listed here - obvious functionality
}
Hopefully that gives an idea, but there are still quite a few potential optimizations. If, for example, you're calculating these intersections for every triangle in a large mesh, you might calculate and cache the DistanceFromPlane once per vertex, and just retrieve it for every edge the vertex participates in. There can be more advanced caching too, depending on your scenario and data representation.
Plug the 3 points into the plane equation (defined by the 4 parameters you listed a,b,c,d) and determine which pairs are on opposite sides of the plane.
Given the plane equation:
Ax + By + Cz + D = 0
where A,B,C is the normal (unit length) and D is the distance to origin IIRC, you plug in points (x,y,z) and see if this result is positive or negative. It will be zero for points on the plane, and the sign will tell you which side a point is on when the result is not 0. So pick pairs of points on opposite sides (there will be at most 2) and compute the intersection of those 2 segments with the plane using a standard ray/plane intersection formula which escapes me right now. Those will be the 2 points that form the segment you seek.
EDIT
Come to think of it, the values you get from plugging the points into the plane equation should be useful for interpolating between pairs of points to get the intersection of segments with the plane.
Len Fn = Axn + Byn + C*zn + D be the result of plugging in point n.
Then suppose F1 = -4 and F2 = 8. So points P1 and P2 are on opposite sides of the plane. We will also have P = P1*2/3 + P2*1/3 is the point of intersection of the segment from P1 to P2 with the plane. Generalizing this into a proper formula is left as an exorcise.
Find the intersection of each line segment bounding the triangle with the plane. Merge identical points, then
if 0 intersections exist, there is no intersection
if 1 intersection exists (i.e. you found two but they were identical to within tolerance) you have a point of the triangle just touching the plane
if 2 points then the line segment between them is the intersection
next step, search SO for line-segment to plane intersection algorithms (or just use the one provided by your framework)...
It depends a bit on what libraries you have. I have created my own geometry library which can calculate the intersection of a line with a plane. In this case calculate the three points of intersection of the three edges of the triangle and then calculate which of them lie between vertices. This could be 0 (no intersection), or 2 which is the case you want. (There are special cases where the two points are coincident - a point of the triangle).
I have information on paths I would like to draw. The information consists of a sequence of straight sections and curves. For straight sections, I have only the length. For curves, I have the radius, direction and angle. Basically, I have a turtle that can move straight or move in a circular arc from the current position (after which moving straight will be in a different direction).
I would like some way to draw these paths with the following conditions:
Minimal (preferably no) trigonometry.
Ability to center on a canvas and scale to fit any arbitrary size.
From what I can tell, GDI+ gives me number 2, Cairo gives me number 1, but neither one makes it particularly easy to get both. I'm open to suggestions of how to make GDI+ or Cairo (preferably pycairo) work, and I'm also open to any other library (preferably C# or Python).
I'm even open to abstract mathematical explanations of how this would be done that I can convert into code.
For 2D motion, the state is [x, y, a]. Where the angle a is relative to the positive x-axis. Assuming initial state of [0, 0, 0]. 2 routines are needed to update the state according to each type of motion. Each path yields a new state, so the coordinates can be used to configure the canvas accordingly. The routines should be something like:
//by the definition of the state
State followLine(State s, double d) {
State s = new State();
s.x = s0.x + d * cos(s0.a);
s.y = s0.y + d * sin(s0.a);
s.a = s0.a;
return s;
}
State followCircle(State s0, double radius, double arcAngle, boolean clockwise) {
State s1 = new State(s0);
//look at the end point on the arc
if(clockwise) {
s1.a = s0.a - arcAngle / 2;
} else {
s1.a = s0.a + arcAngle / 2;
}
//move to the end point of the arc
State s = followLine(s1, 2 * radius * sin(arcAngle/ 2));
//fix new angle
if(clockwise) {
s.a = s0.a - arcAngle;
} else {
s.a = s0.a + arcAngle;
}
return s;
}