Translate origin of rotation matrix - rotational-matrices

I'm applying rotation matrix on Stewart platform joints to get their position referenced to basement.
Code used is here:
for (int i=0; i<6; i++) {
float mx = baseRadius*cos(radians(baseAngles[i]));
float my = baseRadius*sin(radians(baseAngles[i]));
baseJoint[i] = new PVector(mx, my, 0);
}
for (int i=0; i<6; i++) {
float mx = platformRadius*cos(radians(platformAngles[i]));
float my = platformRadius*sin(radians(platformAngles[i]));
platformJoint[i] = new PVector(mx, my, 0);
q[i] = new PVector(0, 0, 0);
l[i] = new PVector(0, 0, 0);
A[i] = new PVector(0, 0, 0);
}
for (int i=0; i<6; i++) {
// rotation
q[i].x = cos(rotation.z)*cos(rotation.y)*platformJoint[i].x +
(-sin(rotation.z)*cos(rotation.x)+cos(rotation.z)*sin(rotation.y)*sin(rotation.x))*platformJoint[i].y +
(sin(rotation.z)*sin(rotation.x)+cos(rotation.z)*sin(rotation.y)*cos(rotation.x))*platformJoint[i].z;
q[i].y = sin(rotation.z)*cos(rotation.y)*platformJoint[i].x +
(cos(rotation.z)*cos(rotation.x)+sin(rotation.z)*sin(rotation.y)*sin(rotation.x))*platformJoint[i].y +
(-cos(rotation.z)*sin(rotation.x)+sin(rotation.z)*sin(rotation.y)*cos(rotation.x))*platformJoint[i].z;
q[i].z = -sin(rotation.y)*platformJoint[i].x +
cos(rotation.y)*sin(rotation.x)*platformJoint[i].y +
cos(rotation.y)*cos(rotation.x)*platformJoint[i].z;
// translation
q[i].add(PVector.add(translation, initialHeight));
l[i] = PVector.sub(q[i], baseJoint[i]);
Each point it's correctly initialized providing their positions by angle. Providing a rotation vector, I've as result a rotated platform based on It's center.
What I'd like to do, is to perform a rotation on arbitrary point (distant x,y,z from platform center) that I provide.
I've thought about 2 methods:
Geometric calculation of each joint respect to a provided point (complex if It's also not on same level). Apply this calculations also on base to have their center perpendicular.
Apply an additional rotation matrix translated by a vector
I'd like a tip about which way is correct (computationally light) or If there's already known way to move rotational center of this points.

Related

Calculating rotation of equally spaced items tangent to spiral

I'd like to programmatically draw a shape like this where there is an underlying spiral and equally spaced objects along it, placed tangent to the spiral as shown in this sketch:
I found an example of how to determine equally spaced points along the spiral here and am now trying to place hemispheres along the spiral. However, I'm not sure how to calculate the angle the shape needs to be rotated.
This is what I have so far (viewable here):
var totalSegments = 235,hw = 320,hh = 240,segments;
var len = 15;
points = [];
function setup(){
createCanvas(640,480);
smooth();
colorMode(HSB,255,100,100);
stroke(0);
noFill();
//println("move cursor vertically");
}
function draw(){
background(0);
translate(hw,hh);
segments = floor(totalSegments);
points = getTheodorus(segments,len);
angles = getAngles(segments, len);
for(var i = 0 ; i < segments ; i++){
let c = color('blue');
fill(c);
noStroke();
// draw shape
if(i % 2){
// console.log(i, ' ', angles[i]);
// try rotating around the object's center
push();
// translate(points[i].x, points[i].y)
rotate(PI/angles[i]);
arc(points[i].x, points[i].y, len*3, len*3, 0, 0 + PI);
pop();
}
// draw spiral
strokeWeight(20);
stroke(0,0,100,(20+i/segments));
if(i > 0) line(points[i].x,points[i].y,points[i-1].x,points[i-1].y);
}
}
function getAngles(segment, len){
let angles = [];
let radius = 0;
let angle = 0;
for(var i =0; i < segments; i++){
radius = sqrt(i+1);
angle += asin(1/radius);
angles[i] = angle;
}
return angles;
}
function getTheodorus(segments,len){
var result = [];
var radius = 0;
var angle = 0;
for(var i = 0 ; i < segments ; i++){
radius = sqrt(i+1);
angle += asin(1/radius);
result[i] = new p5.Vector(cos(angle) * radius*len,sin(angle) * radius*len);
}
return result;
}
Note that your drawing shows Archimedean spiral while link refers to Theodorus one.
Archimedean spiral is described by equation in polar coordinates (rho-theta)
r = a + b * Theta
where a is initial angle, b is scale value (describes distance between arms), r is radius.
And angle Theta + Pi/2 describes normal to spiral in point at parameter Theta
If you need an approximation to divide spiral into (almost) equal segments - use Clackson formula (example here)
theta = 2 * Pi * Sqrt(2 * s / b)
for arc length s

Moving rotated arrow in straight line

I'm trying to move an arrow, which could be rotated, in a straight line. I'm having some difficulty coming up with the correct formula to use. I know it should probably involve sine and cosine, but I've tried various configurations and haven't been able to get something that works.
Here's a picture of my scene with the arrow and bow
rotateNumber is an integer like -1 (for 1 left rotation), 0 (no rotation), 1 (1 right rotation), etc.
rotateAngle is 10 degrees by default.
Here's the code to move the arrow:
if (arrowMoving) {
var rAngle = rotateAngle * rotateNumber;
var angleInRad = rAngle * (Math.PI/180);
var stepSize = 1/20;
arrowX += stepSize * Math.cos(angleInRad);
arrowY += stepSize * Math.sin(angleInRad);
DrawArrowTranslate(arrowX, arrowY);
requestAnimFrame(render);
} else {
DrawArrow();
arrowX = 0;
arrowY = 0;
}
Here's the code to draw and translate the arrow:
function DrawArrowTranslate(tx, ty) {
modelViewStack.push(modelViewMatrix);
/*
var s = scale4(0.3, -0.7, 1);
var t = translate(0, -4, 0);
*/
var s = scale4(0.3, -0.7, 1);
var t = translate(0, -5, 0);
var t2 = translate(0 + tx, 1 + ty, 0)
// rotate takes angle in degrees
var rAngle = rotateAngle;
var r = rotate(rAngle, 0, 0, 1);
var m = mult(t, r);
var m = mult(m, t2);
modelViewMatrix = mat4();
modelViewMatrix = mult(modelViewMatrix, m);
modelViewMatrix = mult(modelViewMatrix, s);
/*
// update bounding box
arrowBoundingBox.translate(0, -5);
arrowBoundingBox.rotate(rAngle);
arrowBoundingBox.translate(0, 1);
arrowBoundingBox.scale(0.3, -0.7);
*/
gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(modelViewMatrix));
gl.drawArrays( gl.LINE_STRIP, 1833, 4);
gl.drawArrays( gl.LINE_STRIP, 1837, 4);
modelViewMatrix = modelViewStack.pop();
}
Your code looks quite correct, but you should eliminate the use of the rotateNumber. You can just use positive and negative angles for rotation instead, eliminating what I imagine is the cause of error here.
Sin and Cos can certainly handle angles of any magnitude positive, negative, or zero.
Good luck!
I figured out the problem. I was translating after rotating when I needed to translate before rotating as the rotation was messing up the translation.

C++ blurring rectangle parts of image

I use MSER algorithm with opencv and find some rectangle parts
then I want to blur that inside rectangle.
my renctangles are vector like (x, y, width, height) but using dilate or erode need inputarray src.
how can i transform vector to inputarray src?
here is my code.
vector< vector< Point> > contours;
vector< Rect> bboxes;
Rect MserROI;
Ptr< MSER> mser = MSER::create(21, (int)(0.00002*textImg.cols*textImg.rows), (int)(0.05*textImg.cols*textImg.rows), 1, 0.7);
mser->detectRegions(textImg, contours, bboxes);
for (int i = 0; i < bboxes.size(); i++)
{
cout << bboxes[i] << '\n';
rectangle(inImg, bboxes[i], CV_RGB(0, 0, 0));
MserROI = bboxes[i];
dilate(MserROI, Mser_dil, Mat(), Point(-1, -1), 2) //error
}
I infer that you want to blur the part of the image that inside the rectangle.
If that's the case, then you need to correct the way you're declaring your ROI.
If 'inImg' is a Mat, then you can declare your ROI as follows:
for (int i = 0; i < bboxes.size(); i++)
{
rectangle(inImg, bboxes[i], CV_RGB(0, 0, 0));
Mat MserROIimg=inImg(bboxes[i]);
dilate(MserROI, Mser_dil, Mat(), Point(-1, -1), 2) //error
}
In your code, you haven't mentioned where you've declared Mser_dil, but if your error is pertaining to ROI declaration, then this should work for you

Change of Steepness, how to do

How would you go about changing the steepness as for loops progress. Essentially I've made a terrain with vertices which form a valley. The creation of the data for these vertices to use is here:
// Divides it to a sensible height
const int DIVISOR_NUMBER = 40;
for (int x = 0; x < TerrainWidth; x++)
{
float height = Math.Abs(((float)x - ((float)TerrainWidth / 2))/ (float)DIVISOR_NUMBER);
for (int y = 0; y < TerrainHeight; y++)
{
float copyOfHeight = height;
float randomValue = random.Next(0, 3);
copyOfHeight += randomValue / 10;
HeightData[x, y] = copyOfHeight;
}
}
This works fine. But I now want to make the sides of the valley steeper at the start and end of the first loop and the valley flatten the closer to the center it gets. I'm having a bit of a mental block and can't think of a good way of doing it. Any help would be appreciated.
You can use a squared (aka quadratic) curve for that. Try:
float offset = (float)x - (float)TerrainWidth/2;
float height = offset*offset*SCALE_FACTOR;
If you still want a "crease" at the bottom of the valley, you can make your height a weighted sum:
float height = Math.Abs(offset) * ABS_FACTOR + offset*offset * QUADRATIC_FACTOR;

How do I optimize displaying a large number of quads in OpenGL?

I am trying to display a mathematical surface f(x,y) defined on a XY regular mesh using OpenGL and C++ in an effective manner:
struct XYRegularSurface {
double x0, y0;
double dx, dy;
int nx, ny;
XYRegularSurface(int nx_, int ny_) : nx(nx_), ny(ny_) {
z = new float[nx*ny];
}
~XYRegularSurface() {
delete [] z;
}
float& operator()(int ix, int iy) {
return z[ix*ny + iy];
}
float x(int ix, int iy) {
return x0 + ix*dx;
}
float y(int ix, int iy) {
return y0 + iy*dy;
}
float zmin();
float zmax();
float* z;
};
Here is my OpenGL paint code so far:
void color(QColor & col) {
float r = col.red()/255.0f;
float g = col.green()/255.0f;
float b = col.blue()/255.0f;
glColor3f(r,g,b);
}
void paintGL_XYRegularSurface(XYRegularSurface &surface, float zmin, float zmax) {
float x, y, z;
QColor col;
glBegin(GL_QUADS);
for(int ix = 0; ix < surface.nx - 1; ix++) {
for(int iy = 0; iy < surface.ny - 1; iy++) {
x = surface.x(ix,iy);
y = surface.y(ix,iy);
z = surface(ix,iy);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix + 1, iy);
y = surface.y(ix + 1, iy);
z = surface(ix + 1,iy);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix + 1, iy + 1);
y = surface.y(ix + 1, iy + 1);
z = surface(ix + 1,iy + 1);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix, iy + 1);
y = surface.y(ix, iy + 1);
z = surface(ix,iy + 1);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
}
}
glEnd();
}
The problem is that this is slow, nx=ny=1000 and fps ~= 1.
How do I optimize this to be faster?
EDIT: following your suggestion (thanks!) regarding VBO
I added:
float* XYRegularSurface::xyz() {
float* data = new float[3*nx*ny];
long i = 0;
for(int ix = 0; ix < nx; ix++) {
for(int iy = 0; iy < ny; iy++) {
data[i++] = x(ix,iy);
data[i++] = y(ix,iy);
data[i] = z[i]; i++;
}
}
return data;
}
I think I understand how I can create a VBO, initialize it to xyz() and send it to the GPU in one go, but how do I use the VBO when drawing. I understand that this can either be done in the vertex shader or by glDrawElements? I assume the latter is easier? If so: I do not see any QUAD mode in the documentation for glDrawElements!?
Edit2:
So I can loop trough all nx*ny quads and draw each by:
GL_UNSIGNED_INT indices[4];
// ... set indices
glDrawElements(GL_QUADS, 1, GL_UNSIGNED_INT, indices);
?
1/. Use display lists, to cache GL commands - avoiding recalculation of the vertices and the expensive per-vertex call overhead. If the data is updated, you need to look at client-side vertex arrays (not to be confused with VAOs). Now ignore this option...
2/. Use vertex buffer objects. Available as of GL 1.5.
Since you need VBOs for core profile anyway (i.e., modern GL), you can at least get to grips with this first.
Well, you've asked a rather open ended question. I'd suggest using modern (3.0+) OpenGL for everything. The point of just about any new OpenGL feature is to provide a faster way to do things. Like everyone else is suggesting, use array (vertex) buffer objects and vertex array objects. Use an element array (index) buffer object too. Most GPUs have a 'post-transform cache', which stores the last few transformed vertices, but this can only be used when you call the glDraw*Elements family of functions. I also suggest you store a flat mesh in your VBO, where y=0 for each vertex. Sample the y from a heightmap texture in your vertex shader. If you do this, whenever the surface changes you will only need to update the heightmap texture, which is easier than updating the VBO. Use one of the floating point or integer texture formats for a heightmap, so you aren't restricted to having your values be between 0 and 1.
If so: I do not see any QUAD mode in the documentation for glDrawElements!?
If you want quads make sure you're looking at the GL 2.1-era docs, not the new stuff.

Resources