Creating a bounding sphere using a GPS coordinate - c++

I would like to create an imaginary bounding sphere around an object. Giving the position of the object in GPS coordinates WGS84 format. And also giving the position in cartesian coordinates.
I have tried to convert degrees lon,lat,alt to radians, and use a function by Spketre, to convert them to Cartesian coordinates.
The problem is I'm doing sphere to sphere collision detection and what I have found that the positions that are converted from spherical to Cartesian are so near so that the sphere intersection method is returning true.
WGS84toXYZ(xAv, yAv, zAv, (m_sPosAV.GetLongitude()*math::pi) / 180, (m_sPosAV.GetLatitude()*math::pi) / 180, (m_sPosAV.GetAltitude()*math::pi) / 180); // lon direction Nort
WGS84toXYZ(xPoi, yPoi, zPoi, (poi.Position().GetLongitude()*math::pi) / 180, (poi.Position().GetLatitude()*math::pi) / 180, (poi.Position().GetAltitude()*math::pi) / 180); // lon direction Nort
Sphere avSphere;
Sphere poiSphere;
avSphere.position.x = xAv;
avSphere.position.y = yAv;
avSphere.position.z = zAv;
avSphere.radius = 1550;
poiSphere.position.x = xPoi;
poiSphere.position.y = yPoi;
poiSphere.position.z = zPoi;
poiSphere.radius = 1200;
if (doesItCollide(avSphere, poiSphere))
{
qDebug() << "collision";
}

Related

Drawing a sprite on the circumference of a circle based on the position of other objects

I'm making a sniper shooter arcade style game in Gamemaker Studio 2 and I want the position of targets outside of the viewport to be pointed to by chevrons that move along the circumference of the scope when it moves. I am using trig techniques to determine the coordinates but the chevron is jumping around and doesn't seem to be pointing to the target. I have the code broken into two: the code to determine the coordinates in the step event of the enemies class (the objects that will be pointed to) and a draw event in the same class. Additionally, when I try to rotate the chevron so it also points to the enemy, it doesn't draw at all.
Here's the coordinate algorithm and the code to draw the chevrons, respectively
//determine the angle the target makes with the player
delta_x = abs(ObjectPlayer.x - x); //x axis displacement
delta_y = abs(ObjectPlayer.y - y); //y axis displacement
angle = arctan2(delta_y,delta_x); //angle in radians
angle *= 180/pi //angle in radians
//Determine the direction based on the larger dimension and
largest_distance = max(x,y);
plusOrMinus = (largest_distance == x)?
sign(ObjectPlayer.x-x) : sign(ObjectPlayer.y-y);
//define the chevron coordinates
chevron_x = ObjectPlayer.x + plusOrMinus*(cos(angle) + 20);
chevron_y = ObjectPlayer.y + plusOrMinus*(sign(angle) + 20);
The drawing code
if(object_exists(ObjectEnemy)){
draw_text(ObjectPlayer.x, ObjectPlayer.y-10,string(angle));
draw_sprite(Spr_Chevron,-1,chevron_x,chevron_y);
//sSpr_Chevron.image_angle = angle;
}
Your current code is slightly more complex that it needs to be for this, if you want to draw chevrons pointing towards all enemies, you might as well do that on spot in Draw. And use degree-based functions if you're going to need degrees for drawing anyway
var px = ObjectPlayer.x;
var py = ObjectPlayer.y;
with (ObjectEnemy) {
var angle = point_direction(px, py, x, y);
var chevron_x = px + lengthdir_x(20, angle);
var chevron_y = py + lengthdir_y(20, angle);
draw_sprite_ext(Spr_Chevron, -1, chevron_x, chevron_y, 1, 1, angle, c_white, 1);
}
(also see: an almost-decade old blog post of mine about doing this while clamping to screen edges instead)
Specific problems with your existing code are:
Using a single-axis plusOrMinus with two axes
Adding 20 to sine/cosine instead of multiplying them by it
Trying to apply an angle to sSpr_Chevron (?) instead of using draw_sprite_ext to draw a rotated sprite.
Calculating largest_distance based on executing instance's X/Y instead of delta X/Y.

Problems rotating objects using eulers - quaternions

I'm having problems rotating GameObjects in my engine. I'm trying to rotate in 2 ways.
I'm using MathGeoLib to calculate maths in the engine.
First way: Rotates correctly around axis but if I want to rotate back, if I don't do it following the inverse order then rotation doesn't work properly.
e.g:
Rotate X axis 50 degrees, Rotate Y axis 30 degrees -> Rotate Y axis -50 degrees, Rotate X axis -30 degrees. Works.
Rotate X axis 50 degrees, Rotate Y axis 30 degrees -> Rotate X axis -50 degrees, Rotate Y axis -30 degrees. Doesn't.
Code:
void ComponentTransform::SetRotation(float3 euler_rotation)
{
float3 diff = euler_rotation - editor_rotation;
editor_rotation = euler_rotation;
math::Quat mod = math::Quat::FromEulerXYZ(diff.x * DEGTORAD, diff.y * DEGTORAD, diff.z * DEGTORAD);
quat_rotation = quat_rotation * mod;
UpdateMatrix();
}
Second way: Starts rotating good around axis but after rotating some times, then it stops to rotate correctly around axis, but if I rotate it back regardless of the rotation order it works, not like the first way.
Code:
void ComponentTransform::SetRotation(float3 euler_rotation)
{
editor_rotation = euler_rotation;
quat_rotation = math::Quat::FromEulerXYZ(euler_rotation.x * DEGTORAD, euler_rotation.y * DEGTORAD, euler_rotation.z * DEGTORAD);
UpdateMatrix();
}
Rest of code:
#define DEGTORAD 0.0174532925199432957f
void ComponentTransform::UpdateMatrix()
{
if (!this->GetGameObject()->IsParent())
{
//Get parent transform component
ComponentTransform* parent_transform = (ComponentTransform*)this->GetGameObject()->GetParent()->GetComponent(Component::CompTransform);
//Create matrix from position, rotation(quaternion) and scale
transform_matrix = math::float4x4::FromTRS(position, quat_rotation, scale);
//Multiply the object transform by parent transform
transform_matrix = parent_transform->transform_matrix * transform_matrix;
//If object have childs, call this function in childs objects
for (std::list<GameObject*>::iterator it = this->GetGameObject()->childs.begin(); it != this->GetGameObject()->childs.end(); it++)
{
ComponentTransform* child_transform = (ComponentTransform*)(*it)->GetComponent(Component::CompTransform);
child_transform->UpdateMatrix();
}
}
else
{
//Create matrix from position, rotation(quaternion) and scale
transform_matrix = math::float4x4::FromTRS(position, quat_rotation, scale);
//If object have childs, call this function in childs objects
for (std::list<GameObject*>::iterator it = this->GetGameObject()->childs.begin(); it != this->GetGameObject()->childs.end(); it++)
{
ComponentTransform* child_transform = (ComponentTransform*)(*it)->GetComponent(Component::CompTransform);
child_transform->UpdateMatrix();
}
}
}
MathGeoLib:
Quat MUST_USE_RESULT Quat::FromEulerXYZ(float x, float y, float z) { return (Quat::RotateX(x) * Quat::RotateY(y) * Quat::RotateZ(z)).Normalized(); }
Quat MUST_USE_RESULT Quat::RotateX(float angle)
{
return Quat(float3(1,0,0), angle);
}
Quat MUST_USE_RESULT Quat::RotateY(float angle)
{
return Quat(float3(0,1,0), angle);
}
Quat MUST_USE_RESULT Quat::RotateZ(float angle)
{
return Quat(float3(0,0,1), angle);
}
Quat(const float3 &rotationAxis, float rotationAngleRadians) { SetFromAxisAngle(rotationAxis, rotationAngleRadians); }
void Quat::SetFromAxisAngle(const float3 &axis, float angle)
{
assume1(axis.IsNormalized(), axis);
assume1(MATH_NS::IsFinite(angle), angle);
float sinz, cosz;
SinCos(angle*0.5f, sinz, cosz);
x = axis.x * sinz;
y = axis.y * sinz;
z = axis.z * sinz;
w = cosz;
}
Any help?
Thanks.
Using Euler angles and or Quaternions adds some limitations as it creates singularities which if not handled correctly will make silly things. Sadly almost all new 3D games using it wrongly. You can detect those by the well known things like:
sometimes your view get to very different angle that should not be there
object can not rotate anymore in some direction
object start rotating around different axises than it should
view jumps around singularity pole
view is spinning or flipping until you move/turn again (not the one caused by optic mouse error)
I am using cumulative transform matrices instead:
Understanding 4x4 homogenous transform matrices
Read the whole stuff (especially difference between local and global rotations) then in last 3 links you got C++ examples of how to do this (also read all 3 especially the preserving accuracy ...).
The idea is to have matrix representing your object coordinate system. And when ever you rotate (by mouse, keyboard, NAV,AI,...) you rotate the matrix (incrementally). The same goes for movement. This way they are no limitations or singularities. But also this approach has its problems:
lose of accuracy with time (read the preserving accuracy example to deal with this)
no knowledge about the Euler angles (the angles can be computed from the matrix however)
Both are solvable relatively easily.
Now when you are rotating around local axises you need to take into account that with every rotation around some axis you change the other two. So if you want to get to the original state you need to reverse order of rotations because:
rotate around x by 30deg
rotate around y by 40deg
is not the same as:
rotate around y by 40deg
rotate around x by 30deg
With cumulative matrix if you want to get back you can either iteratively drive your ship until it faces desired directions or remember original matrix and compute the rotations needed to be done one axis at a time. Or convert the matrix difference into quaternion and iterate that single rotation...

Collision between two GPS points

I would like to do sphere to sphere intersection or ellipsoid to ellipsoid if I have two GPS coordinate points. What is the formula for that ?
Suppose I have two GPS points with two different lon,lat,alt. I would like to do sphere to sphere intersection or ellipsoid to ellipsoid. Is there a formula for that ?
WGS84toXYZ(xAv, yAv, zAv, (m_sPosAV.GetLongitude()*math::pi) / 180, (m_sPosAV.GetLatitude()*math::pi) / 180, (m_sPosAV.GetAltitude()*math::pi) / 180); // lon direction Nort
WGS84toXYZ(xPoi, yPoi, zPoi, (poi.Position().GetLongitude()*math::pi) / 180, (poi.Position().GetLatitude()*math::pi) / 180, (poi.Position().GetAltitude()*math::pi) / 180); // lon direction Nort
Sphere avSphere;
Sphere poiSphere;
avSphere.position.x = xAv;
avSphere.position.y = yAv;
avSphere.position.z = 0;
avSphere.radius = 1550000;
poiSphere.position.x = xPoi;
poiSphere.position.y = yPoi;
poiSphere.position.z = 0;
poiSphere.radius = 100000;
if (doesItCollide(avSphere, poiSphere))
{
qDebug() << "collision sphere";
}
Sphere is easy:
If distance between your 2 points is smaller than the sum of your radii for the spheres, you got yourself an intersection.

draw circle in XPS document API

How can I draw a circle with XPS document API?
I use following code, bit the circle is not drawn at all if start point and end point of circle is same. It draws "the arc of angle zero instead"..
XPS_POINT startPoint = { 500, 500};
hr = xpsFactory->CreateGeometryFigure(&startPoint, &figure);
XPS_SEGMENT_TYPE segmentTypes[1] = {
XPS_SEGMENT_TYPE_ARC_LARGE_COUNTERCLOCKWISE
};
// x - coordinate of the arc's end point.
// y - coordinate of the arc's end point.
// Length of the ellipse's radius along the x-axis.
// Length of the ellipse's radius along the y-axis.
// Rotation angle.
FLOAT segmentData[5] = {
startPoint.x, // if it is startPoint.x + 0.001, I see kind pf a circle
startPoint.y,
radius,
radius,
360
};
BOOL segmentStrokes[1] = {
TRUE// Yes, draw each of the segment arcs.
};
// Add the segment data to the figure.
hr = figure->SetSegments(
1,
5,
segmentTypes,
segmentData,
segmentStrokes);
hr = figure->SetIsClosed(TRUE);
hr = figure->SetIsFilled(TRUE);

Rotation matrix - rotate a ball around a rotating box

I've a 3D box: center point = (a,b,c), width = w, height = h, depth = d.
the center point isn't the origin.
I have a ball on the box(touch each other), its center and radius.
I can rotate the box(around the X axis but its center STAYS the same..) and I want the ball to stay stuck to the box. so the ball needs to be rotated WITH the box.
the angle of the rotation is 45 degrees.
I tried to do this:
I defined the Rotation Matrix around the X axis:
mat[3][3]
1, 0 , 0
0, cos(45), -sin(45)
0, sin(45), cos(45)
and multiply it by the ball center vector:
(ball.Center().m_x , ball.Center().m_y, ball.Center().m_z) * mat
so I got:
Point3D new_center(ball.Center().m_x,
ball.Center().m_y*cos(45) + ball.Center().m_z*sin(45),
-(ball.Center().m_y)*sin(45) + ball.Center().m_z*cos(45));
ball.Center() = new_center;
the ball is really rotated when the box is rotated but too far. How can I fix it?
Have you tried to translate it to the origin of coordinates, rotate and then translate back?
And I think that the coordinates should be multiplied on the right by the transformation matrix, i.e.:
Point3D new_center(ball.Center().m_x,
ball.Center().m_y*cos(45) - ball.Center().m_z*sin(45),
ball.Center().m_y*sin(45) + ball.Center().m_z*cos(45);
ball.Center() = new_center;
thanks to Alexander Mihailov, here's the final answer:
// correcting the ball center to the origin according the box.Center
Point3D ball_center_corrected = ball.Center() - box.Center();
// rotation_matrix(of X axis) * ball_center_corrected
// so the rotation is around the X axis
Point3D new_center(ball_center_corrected.m_x,
ball_center_corrected.m_y*cos(angle) -
ball_center_corrected.m_z*sin(angle),
ball_center_corrected.m_y*sin(angle) +
ball_center_corrected.m_z*cos(angle));
// translate the ball center back around the box
ball.Center() = new_center + box.Center();