Get point around rounded rectangle - c++

I'm using this to get a point around a circle.
constexpr int quality = 20;
static Vertex_t verts[quality];
for ( int i = 0; i < quality; i++ ) {
float angle = ((float)i / -quality) * MATH_TAU;
verts[i].x = cir.pos.x + (cir.radius * sin( angle ));
verts[i].y = cir.pos.y + (cir.radius * cos( angle ));
}
now i need to get a point around a rounded rectangle given it's position, size and radius.

You'll have to split the code to 4 - one for each corner. As these are vertices you're dealing with, the straight lines will be filled automatically.

Related

how to implement a c++ function which creates a swirl on an image

imageData = new double*[imageHeight];
for(int i = 0; i < imageHeight; i++) {
imageData[i] = new double[imageWidth];
for(int j = 0; j < imageWidth; j++) {
// compute the distance and angle from the swirl center:
double pixelX = (double)i - swirlCenterX;
double pixelY = (double)j - swirlCenterY;
double pixelDistance = pow(pow(pixelX, 2) + pow(pixelY, 2), 0.5);
double pixelAngle = atan2(pixelX, pixelY);
// double swirlAmount = 1.0 - (pixelDistance/swirlRadius);
// if(swirlAmount > 0.0) {
// double twistAngle = swirlTwists * swirlAmount * PI * 2.0;
double twistAngle = swirlTwists * pixelDistance * PI * 2.0;
// adjust the pixel angle and compute the adjusted pixel co-ordinates:
pixelAngle += twistAngle;
pixelX = cos(pixelAngle) * pixelDistance;
pixelY = sin(pixelAngle) * pixelDistance;
// }
(this)->setPixel(i, j, tempMatrix[(int)(swirlCenterX + pixelX)][(int)(swirlCenterY + pixelY)]);
}
}
I am trying to implement a c++ function (code above) based on the following pseudo-code
which is supposed to create a swirl on an image, but I have some continuity problems on the borders.
The function I have for the moment is able to apply the swirl on a disk of a given size and to deform it almost as I whished but its influence doesn't decrease as we get close to the borders. I tried to multiply the angle of rotation by a 1 - (r/R) factor (with r the distance between the current pixel in the function and the center of the swirl, and R the radius of the swirl), but this doesn't give the effect I hoped for.
Moreover, I noticed that at some parts of the border, a thin white line appears (which means that the values of the pixels there is equal to 1) and I can't exactly explain why.
Maybe some of the problems I have are linked to the atan2 C++ standard function.

How draw axis of ellipse

I am using fitellipse of Opencv and C++, and I'm getting these values:
/// Find the rotated rectangles and ellipses for each contour
vector<RotatedRect> minRect( contours.size() );
vector<RotatedRect> minEllipse( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{
minRect[i] = minAreaRect( Mat(contours[i]) );
if( contours[i].size() > 5 )
minEllipse[i] = fitEllipse( Mat(contours[i]) );
// ...
}
float xc = minEllipse[element].center.x;
float yc = minEllipse[element].center.y;
float a = minEllipse[element].size.width / 2;
float b = minEllipse[element].size.height / 2;
float theta = minEllipse[element].angle;
But with these values how can I draw the axis of an ellipse, for example of the following ellipse?
NOTE: Element is an ellipse stored in minEllipse.
You can use minEllipse[element].points to get the four corners of the rotated bounding rectangle, like described here.
Then you only need to calculate the average of the two points on each side of the rectangle to get the endpoints for the axes...
Point2f vertices[4];
minEllipse[element].points(vertices);
line(image, (vertices[0] + vertices[1])/2, (vertices[2] + vertices[3])/2, Scalar(0,255,0));
line(image, (vertices[1] + vertices[2])/2, (vertices[3] + vertices[0])/2, Scalar(0,255,0));
You are probably looking for those formulas:
ct = cos(theta)
st = sin(theta)
LongAxix0.x = xc - a*ct
LongAxis0.y = yc - a*st
LongAxis1.x = xc + a*ct
LongAxix1.y = yc + a*st
ShortAxix0.x = xc - b*st
ShortAxix0.y = yc + b*ct
ShortAxis1.x = xc + b*st
ShortAxix2.y = yc - b*ct
But with these values how can I draw the axis of an ellipse?
The axis of the ellipse are passing through its centre:
float xc = minEllipse[element].center.x;
float yc = minEllipse[element].center.y;
the start and end points of the axis could be at an offset from the centre defined by the ellipse's width and height, i.e.:
// horizontal axis start/ end point
// coordinates
int HxStart = xc - size.width / 2;
int HyStart = yc;
int HxEnd = xc + size.width / 2;
int HyEnd = yc;
// points
Point Hstart(HxStart, HyStart);
Point Hend(HxEnd, HyEnd);
// horizontal axis
Line horizontalAxis(Hstart, Hend);
// vertical axis start/ end point
int VxStart = xc;
int VyStart = yc - size.height / 2;
int VxEnd = xc;
int VyEnd = yc + size.height / 2;
// ----//----
Now, you can rotate the axis (the above for points) by the provided angle theta, around the centre of the ellipse.
Having the above and knowing how to construct a line you can build the two axis at any given angle theta.

How to rotate the contents of 16x16 bitmap array using only maths (no scaling, just clip the corners off)

another question from me about bitmaps! A quick intro to this: I'm working on a university project where I have no external libraries, only the basic windows/c++, this bitmap rotation must be done entirely by simply modifying pixels in an array.
I have a 16x16 bitmap (it's just a COLORREF array that's 16x16 elements long) and I want to rotate it about the centre point (or any point actually).
I have some code that almost works, it rotates it about the top-left corner so I know I'm close, I just don't know what to edit to offset that by 8 pixels as everything I can think of results in overflowing out of the 16x16 area.
Here's the code I currently have (which I grabbed from DrDobbs and modified it a bit, it had a scaling parameter (the (1.0) parts) which I didn't need).
void Sprite::DrawAt(Render* render, int x, int y, double angle)
{
COLORREF* tmp = new COLORREF[width * height];
int u, v;
for (int i = 0; i<height; i++)
{
for (int j = 0; j<width; j++)
{
u = cos(-angle) * j * (1.0) + sin(-angle) * i * (1.0);
v = -sin(-angle) * j * (1.0) + cos(-angle) * i * (1.0);
tmp[(i * width) + j] = bitmap[(v * width) + u];
}
}
// x-(width/2) renders it at the centre point instead of the top-left
render->BlockShiftBitmap(tmp, x - (width/2), y - (height/2), width, height, -1);
delete[] tmp;
}
(Excuse some of the bad coding habits here, I'm only interested in the topic at hand, everything else will get cleaned up another time).
That code results in this:
http://puu.sh/hp4nB/8279cd83dd.gif http://puu.sh/hp4nB/8279cd83dd.gif
It rotates around the top-left corner, and it also grabs out of bounds memory too. I could do with a solution that rotates around the centre (or any point, that would come in handy later on for things such as doors!) and also clips off the corners and ensures no random bits of memory end up in the resulting bitmap.
The result should hopefully look something like this with the black pixels turned white:
http://puu.sh/hp4uc/594dca91da.gif http://puu.sh/hp4uc/594dca91da.gif
(don't ask what the hell that creature is! he's some kind of red-eared debug-lizard)
Thanks, you awesome people here have helped quite a bit on this little project of mine!
could you try subtracting 8 from i's and j's
u = cos(-angle) * (j-8) * (1.0) + sin(-angle) * (i-8) * (1.0);
v = -sin(-angle) * (j-8) * (1.0) + cos(-angle) * (i-8) * (1.0);
To rotate around an origin (ox, oy), first substract these coordinates, then rotate, and then add them again.
// Choose the center as the origin
ox = width / 2;
oy = height / 2;
// Rotate around the origin by angle
u = cos(-angle) * (j-ox) + sin(-angle) * (i-oy) + ox;
v = -sin(-angle) * (j-ox) + cos(-angle) * (i-oy) + oy;
Then, add a bounds check before accessing your image, and use a replacement color for the "background", in case the coordinates are not within the bounds:
if (u >= 0 && u < width && v >= 0 && v < height)
tmp[(i * width) + j] = bitmap[(v * width) + u];
else
tmp[(i * width) + j] = 0; // However you represent white...

Finding verticies of a polygon given the number of sides? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to a function that will find all the vertices of a polygon given X number of sides and a radius r. My overall goal is to make a circle but since you can only draw straight lines I will have to make a polygon. So all of the polygons are going to be centred on the point (0,0). And I want to find all the coordinates for a polygon with 6 sides and radius that will iterate from .1 to 1.0. This should form a 10 circles inside of each other.
Here is what I have so far:
Here are my errors:
52:33: error: variable-sized object ‘vertices’ may not be initialized
57:17: error: request for member ‘insert’ in ‘vertices’, which is of non-class type ‘iPoint [(((long unsigned int)(((long int)nVertices) + -0x00000000000000001)) + 1)]’
My goal for the for loop is to get all the coordinates for a single polygon for the given radius and stick them in the verticies array as a 2 dimensional Point (x coordinate and a y coordinate).
I would take Point vertices[nVerticies] = {}; out of the loop (before the for). I would additionally correct verticies to vertices. Also, math functions sin and cos usually work in radians, not degrees. Finally, the angle increment can't be constant but depend (inversely) on nVertices.
Taking all together:
double radius = 0.1;
int nVertices = 6;
double angle = pi()*2/nVertices ;
while(radius <= 1.0)
{
iPoint vertices[nVertices];
for (int i = 0; i < nVertices; i++)
{
double x = 0 + radius * sin(i * angle);
double y = 0 + radius * cos(i * angle);
vertices[i]= iPoint(x,y) ;
}
radius = radius + 0.1;
}
Is there any advice?
The angular distance between two points on a regular flat 2D polygon is 2pi / N
Update due to comment
I'd write it slightly differently.
#include <math.h> // for M_PI
void circle_points(
double const radius,
int const n_points,
std::vector<Point<double>> &out_points )
{
out_points.resize(n_points);
double const angular_distance = M_PI / (double)n_points;
for( int i = 0; i < n_points; i++ ) {
double const x = radius * sin(i * angular_distance);
double const y = radius * cos(i * angular_distance);
out_points[i] = Point<double>(x,y);
}
}
void concentric_circles(
double const radius_start,
double const radius_end,
int const n_circles,
int const n_points_per_circle,
std::vector<std::vector<Point<double>> &out_circles )
{
out_circles.resize(n_circles);
double const radius_increment = (radius_end - radius_start) / n_circles;
for( int i = 0; i < n_circles; i++ ) {
circle_points(
radius_start + radius_increment*i,
n_points_per_circle,
out_circles[i] );
}
}
I'm passing the vectors by reference here to avoid deep copies when entering / leaving the function scopes.
If you would like vertices to be a static array and initialize it , declare 'nVertices' as a macro or const int.
const int nVertices = 6;

Implementing seek behaviour of objects on a plane in OpenSceneGraph?

I have created an open plane area with thin cylinders on it like pucks, they bounce around the area and have collision detection for some larger cylinders also placed on the plane. I am trying to get them to now head towards a set point on the plane using a steering method.
The steering works for works for avoiding the obstacles by calculating distance from obstacle then calculating angle between direction travelling and the direction of the obstacle, using the calculation of the distance from obstacle when the puck is too close it steers left or right based on the calculated angle. The same technique reversed fails to work for steering towards a point, I have tried using both acos and atan2 to calculate the angle between direction travelling and target direction and from outputs believe this bit is right but when I try to use that calculation to determine when to steer towards the target I get unexpected results. Sometimes random turning?
#include "Puck.h"
#include <iostream>
#include <fstream>
using namespace std;
#include <math.h>
ofstream fout("danna.txt");
#ifndef M_PI
#define M_PI 3.1415
#endif
class TranslateCB : public osg::NodeCallback
{
public:
TranslateCB() : _dx( 0. ), _dy( 0. ), _dirx(1), _diry(0), _inc(0.1), _theta(0) {}
TranslateCB(Puck** pp, Obstacle** ob, int count, double r, double x, double y) : _dx( 0. ), _dy( 0. ),
_dirx(2.0*rand()/RAND_MAX-1), _diry(2.0*rand()/RAND_MAX-1), _inc(0.3), _theta(0)
{
obstacles = ob;
ob_count = count;
_radius = r;
_x = x;
_y = y;
puckH = pp;
}
virtual void operator()( osg::Node* node,osg::NodeVisitor* nv )
{
osg::MatrixTransform* mt =
dynamic_cast<osg::MatrixTransform*>( node );
osg::Matrix mR, mT;
mT.makeTranslate( _dx , _dy, 0. );
mt->setMatrix( mT );
double ob_dirx;
double ob_diry;
double ob_dist;
double centerX=0, centerY =0;
_theta = 0;
double min = 4;
// location that I am trying to get the pucks to head towards
centerX = 1;
centerY = 5;
double tDirx = (_x+_dx) - centerX;
double tDiry = (_y+_dy) - centerY;
double tDist = sqrt(tDirx*tDirx+tDiry*tDiry); //distance to target location
// normalizing my target direction
tDirx = tDirx/tDist;
tDiry = tDiry/tDist;
double hDist = sqrt(_dirx*_dirx + _diry*_diry); //distance to next heading
_dirx= _dirx/hDist;
_diry= _diry/hDist;
double cAngle = acos(_dirx*tDirx+_diry*tDiry); //using inverse of cos to calculate angle between directions
double tAngle = atan2(centerY - (_y+_dy),centerX - (_x+_dx)); // using inverse of tan to calculate angle between directions
double tMin = tDist*sin(cAngle);
//if statement used to define when to apply steering direction
if(tMin > 3)
{
if(tDist < 1){ _theta = 0; } //puck is inside target location, so keep travelling straight
if(cAngle > M_PI/2){ _theta = -0.1; } //turn left
else{ _theta = 0.1; } //turn right
}
else{ _theta = 0; }
////// The collision detection for the obstacles that works on the same princables that I am using above
for(int i = 0; i < ob_count; i++)
{
ob_dirx = (_x+_dx) - obstacles[i]->x;
ob_diry = (_y+_dy) - obstacles[i]->y;
ob_dist = sqrt(ob_dirx*ob_dirx+ob_diry*ob_diry);
if (ob_dist < 3) {
//normalise directions
double ob_norm = sqrt(ob_dirx*ob_dirx+ob_diry*ob_diry);
ob_dirx = (ob_dirx)/ob_norm;
ob_diry = (ob_diry)/ob_norm;
double norm = sqrt(_dirx*_dirx+_diry*_diry);
_dirx = (_dirx)/norm;
_diry = (_diry)/norm;
//calculate angle between direction travelling, and direction to obstacle
double angle = acos(_dirx*ob_dirx + _diry*ob_diry);
//calculate closest distance between puck and obstacle if continues on same path
double min_dist = ob_dist*sin(angle);
if(min_dist < _radius + obstacles[i]->radius && ob_dist < min+obstacles[i]->radius)
{
min = ob_dist;
if(ob_dist < _radius + obstacles[i]->radius){ _theta = 0; }
else if(angle <= M_PI/2){ _theta = -0.3; }
else{ _theta = 0.3; }
}
}
}
//change direction accordingly
_dirx = _dirx*cos(_theta) + _diry*sin(_theta);
_diry = _diry*cos(_theta) - _dirx*sin(_theta);
_dx += _inc*_dirx;
if((_x+_dx > 20 && _dirx > 0) || (_x+_dx < -20 && _dirx < 0))
{
_dirx = -_dirx;
_diry += (0.2*rand()/RAND_MAX-0.1); //add randomness to bounce
}
_dy += _inc*_diry;
if((_y+_dy > 20 && _diry > 0) || (_y+_dy < -20 && _diry < 0))
{
_diry = -_diry;
_dirx += (0.2*rand()/RAND_MAX-0.1); //add randomness to bounce
}
traverse( node, nv );
}
private:
double _dx,_dy;
double _dirx,_diry;
double _inc;
double _theta;
double _radius;
double _x,_y;
Obstacle** obstacles;
Puck** puckH;
int ob_count;
};
Puck::Puck()
{
}
void Puck::createBoids (Puck** pucks, Group *root, Obstacle** obstacles, int count, double xx, double yy)
{
// geometry
radius = 0.2;
x = xx;
y = yy;
ob_count = count;
Cylinder *shape=new Cylinder(Vec3(x,y,0),radius,0.1);
ShapeDrawable *draw=new ShapeDrawable(shape);
draw->setColor(Vec4(1,0,0,1));
Geode *geode=new Geode();
geode->addDrawable(draw);
// transformation
MatrixTransform *T=new MatrixTransform();
TranslateCB *tcb = new TranslateCB(pucks, obstacles,ob_count,radius,x,y);
T->setUpdateCallback(tcb);
T->addChild(geode);
root->addChild(T);
}
any help would be amazing!
The problem here is that the technique that "works" for avoiding obstacles will always occur when the puck is heading towards the obstacle. This special condition makes both the direction of the puck and the direction of the obstacle in adjacent quadrants.
When attempting to make the pucks steer towards the obstacle however, the technique breaks down because the puck most likely will be heading away from the obstacle, no longer having the condition that the target and direction vectors are in adjacent quadrants.
The correct way to determine the steering direction is to rotate the target vector by an angle that would make the the direction vector point straight up in the quadrants (0, 1). Now that the target vector is relative to the direction vector (0, 1) looking at the x component of the target vector will determine the steering direction. If the x component of the target vector is negative, the puck must turn left to steer towards the target (increase the angle). If the x component of the target vector is positive, the puck must turn right to steer towards the target (decrease the angle).
Consider the following snippet written in python to verify this, it should still be easy to read for you to grasp the concept:
from math import *
dirX = 0.0
dirY = 0.0
targX = 1.0
targY = 0.0
def dir():
global dirX, dirY, targX, targY
# get magnitiude of direction
mag1 = sqrt(dirX*dirX + dirY*dirY)
if mag1 != 0:
# normalize direction vector
normX = dirX / mag1
normY = dirY / mag1
# get magnitude of target vector
mag2 = sqrt(targX*targX + targY*targY)
if mag2 != 0:
# normalize target vector
targX = targX / mag2
targY = targY / mag2
# find the angle need to rotate the dir vector to (0, 1)
rotateAngle = (pi/2.0) - atan2(normY, normX)
# rotate targ vector by that angle (we only care about the x component)
relTargX = cos(rotateAngle) * normX + sin(rotateAngle) * normY
# if the target vector's x is negative
if relTargX < 0:
# turn left
print "Left!"
# otherwise the target vector is 0 or positive
else:
# turn right
print "Right!"
def out():
global dirX, dirY, targX, targY
# function just prints values to the screen
print "dir(%f, %f) targ(%f, %f)" % (dirX, dirY, targX, targY)
# for values 0 to 360
for i in range(360):
# pretend this is the pucks direction
dirX = sin(radians(i))
dirY = cos(radians(i))
# print dir and target vectors to screen
out()
# print the direction to turn
dir()
I suppose I could've written this in C++, but compared to running a python prompt it's a royal pain. It is as readable as any pseudo code I could've written and the concepts will work regardless of language.