I am pasting code below to track both eyes and overlay an image when both eyes are tracked.
I am using haar xml files to track both eyes of faces and overlaying an image over it.
My problem is I get result like this.
Img 1
Img 2
Img 3
Img 4
Img 5
Img 6
Img 7
Img 8
Img 9
Img 10
I am posting my code below
#include "cv.h"
#include "highgui.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <sys/stat.h>
#include <ctype.h>
#include <string>
using namespace cv;
using namespace std;
void detectAndDisplay( Mat frame );
String face_cascade_name = "/root/opencv/newtutorial/haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "/root/opencv/newtutorial/haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
RNG rng(12345);
IplImage *disp,*neg_img,*cpy_img,*imga;
IplImage *pic;
IplImage *image_n = 0;
int make=0;
CvMat* warp_matrix = cvCreateMat(3,3,CV_32FC1);
namespace {
void makevdo(){
bool flag = false;
fstream fin;
char filename_new[200],filename_new_after[200];
int n=0;
Mat frame;
double frameRate = 25.0;
CvVideoWriter *vdowriter = cvCreateVideoWriter( "/root/opencv/newtutorial/test_converted_next.mov", CV_FOURCC('j','p','e','g'), frameRate, Size(640,480) );
VideoWriter(outputFile,CV_FOURCC('j','p','e','g'),frameRate,Size(640,480));
while(flag==false){
sprintf(filename_new,"/root/opencv/newtutorial/mydirnext/filename%.3d.jpg",n);
sprintf(filename_new_after,"/root/opencv/newtutorial/framesaftertrack/filename%.3d.jpg",n);
fin.open(filename_new,ios::in);
if( fin.is_open() )
{
frame = imread(filename_new);
pic = cvLoadImage("/root/opencv/newtutorial/pic.png");
image_n = cvLoadImage(filename_new,1);
disp = cvCreateImage( cvGetSize(image_n), 8, 3 );
cpy_img = cvCreateImage( cvGetSize(image_n), 8, 3 );
neg_img = cvCreateImage( cvGetSize(image_n), 8, 3 );
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
CvPoint2D32f q[4];
q[0].x= (float) pic->width * 0;
q[0].y= (float) pic->height * 0;
q[1].x= (float) pic->width;
q[1].y= (float) pic->height * 0;
q[2].x= (float) pic->width;
q[2].y= (float) pic->height;
q[3].x= (float) pic->width * 0;
q[3].y= (float) pic->height;
for( int i = 0; i < (int)faces.size(); i++ )
{
faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 2, 8, 0 );
Mat faceROI = frame_gray( faces[i] );
std::vector<Rect> eyes;
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );
if((int)eyes.size()==2 && (((eyes[0].x + eyes[0].width*0.5 ) < eyes[1].x) || ((eyes[1].x + eyes[1].width*0.5 ) < eyes[0].x))){
CvPoint2D32f p[4];
IplImage* blank = cvCreateImage( cvGetSize(pic), 8, 3);
cvZero(blank);
cvNot(blank,blank);
if(eyes[0].x<eyes[1].x){
Point center0( faces[i].x + eyes[0].x + eyes[0].width*0.5, faces[i].y + eyes[0].y + eyes[0].height*0.5 );
float radius0 = (eyes[0].width + eyes[0].height)*0.25 ;
Point center1( faces[i].x + eyes[1].x + eyes[1].width*0.5, faces[i].y + eyes[1].y + eyes[1].height*0.5 );
float radius1 = (eyes[1].width + eyes[1].height)*0.25 ;
p[2].x= (float) center0.x - radius0;
p[2].y= (float) center0.y + radius0;
p[1].x= (float) center0.x - radius0;
p[1].y= (float) center0.y - radius0;
p[3].x= (float) center1.x + radius1;
p[3].y= (float) center1.y + radius1;
p[0].x= (float) center1.x + radius1;
p[0].y= (float) center1.y - radius1;
}
else{
Point center0( faces[i].x + eyes[1].x + eyes[1].width*0.5, faces[i].y + eyes[1].y + eyes[1].height*0.5 );
float radius0 = (eyes[1].width + eyes[1].height)*0.25 ;
Point center1( faces[i].x + eyes[0].x + eyes[0].width*0.5, faces[i].y + eyes[0].y + eyes[0].height*0.5 );
float radius1 = (eyes[0].width + eyes[0].height)*0.25 ;
p[2].x= (float) center0.x - radius0;
p[2].y= (float) center0.y + radius0;
p[1].x= (float) center0.x - radius0;
p[1].y= (float) center0.y - radius0;
p[3].x= (float) center1.x + radius1;
p[3].y= (float) center1.y + radius1;
p[0].x= (float) center1.x + radius1;
p[0].y= (float) center1.y - radius1;
}
cvGetPerspectiveTransform(q,p,warp_matrix);
cvZero(neg_img);
cvZero(cpy_img);
cvWarpPerspective( pic, neg_img, warp_matrix);
cvWarpPerspective( blank, cpy_img, warp_matrix);
cvNot(cpy_img,cpy_img);
cvAnd(cpy_img,image_n,cpy_img);
cvOr(cpy_img,neg_img,image_n);
}
}
cvSaveImage(filename_new_after,image_n);
cvWriteFrame(vdowriter,image_n);
cout<<"Read file filename"<< n <<endl;
}
else{
flag=true;
}
fin.close();
n++;
}
cvReleaseVideoWriter(&vdowriter);
cvReleaseImage(&pic);
cvReleaseImage(&imga);
cvReleaseImage(&disp);
cvReleaseImage(&neg_img);
cvReleaseImage(&cpy_img);
cvReleaseImage(&image_n);
}
int process(VideoCapture& capture) {
char strFrame[]="/root/opencv/newtutorial/mydirnext";
if(mkdir(strFrame,0777)==-1)
{
cout<<"Error Trying to delete"<<endl;
if(system("rm -r /root/opencv/newtutorial/mydirnext")){
cout << "Directory successfully deleted"<<endl;
}
if(mkdir(strFrame,0777)==-1){
cout << "Error Again creating directory" << endl;
}
}
int n = 0;
char filename[200];
string window_name = "video | q or esc to quit";
cout << "press space to save a picture. q or esc to quit" << endl;
namedWindow(window_name, CV_WINDOW_KEEPRATIO);
Mat frame;
for (;;) {
capture >> frame;
if (frame.empty())
continue;
imshow(window_name, frame);
sprintf(filename,"/root/opencv/newtutorial/mydirnext/filename%.3d.jpg",n++);
imwrite(filename,frame);
char key = (char)waitKey(5);
switch (key) {
case 27:
if(make==0){
make=1;
makevdo();
}
return 0;
default:
break;
}
}
return 0;
}
}
int main(int ac, char** av) {
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
if( !eyes_cascade.load( eyes_cascade_name ) ){ printf("--(!)Error loading\n"); return -1; };
if (ac != 2) {
return 1;
}
std::string arg = av[1];
VideoCapture capture(arg);
if (!capture.isOpened())
capture.open(atoi(arg.c_str()));
if (!capture.isOpened()) {
cerr << "Failed to open a video device or video file!\n" << endl;
return 1;
}
return process(capture);
}
Sorry for posting so many Images SO, but No other way to explain my problem.
Start by extracting everything to methods/functions that you can be given a sensible name. We don't want to see methods longer than 10 lines. The images are not helpful at all. Remove the overlay and show what the algorithm claims to recognize, when it does so.
After you've done that, feed it sequences of the same images. First the ones where it recognizes, then those where it doesn't. That way you can get a better guess where the problem is. But first clean up the messy code.
Related
I need to learn this stuff in order to pass the exams so
I tried this code but it didn’t work. How can I get it to work?
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include "img_header.h"
('img_header.h' contains some functions)
void simple_rgb_image_init(Simple_RGB_Image* sink, int32_t width, int32_t height);
typedef struct {
int32_t width;
int32_t height;
uint8_t* data;
} Simple_RGB_Image;
int main()
{
Simple_RGB_Image img;
int32_t width = 3;
int32_t height = 3;
FILE* out_file;
int32_t w;
int32_t x,y ;
uint8_t red,green,blue;
uint8_t* p_red;
uint8_t* p_green;
uint8_t* p_blue;
p_red = &red;
p_green = &green;
p_blue = &blue;
simple_rgb_image_init(&img,width,height);
x = 1 ;
y = 1 ;
w = calculate_stride(width); //calculate the stride
blue = img.data[3 *(w*y + x) + 0];
green = img.data[3 *(w*y + x) + 1];
red = img.data[3 *(w*y + x) + 3];
printf("blue = %i \n" , blue); //205
printf("green = %i \n" , green);//205
printf("red = %i \n" , red); //205
printf("\n\n");
*p_red = 0;
*p_green = 0;
*p_blue = 255;
printf("blue = %i \n" , blue); //255
printf("green = %i \n" , green);//0
printf("red = %i \n" , red); //0
out_file = fopen("My_picture.bmp","wb");
simple_rgb_image_to_bitmap_stream(&img,out_file); //save the picture as a Bitmap file
fclose(out_file);
simple_rgb_image_clear(&img); //Free memory
return 0;
}
void simple_rgb_image_init(Simple_RGB_Image* sink, int32_t width, int32_t height)
{
sink->width = width;
sink->height = height;
sink->data = (uint8_t*)malloc(3 * width * height);
}
I did dealt directly with pointers , but in vain ! The code is still generating a 9 Pixels Bitmap-image ,with the color (Red = 205 , Blue = 205 , Green = 205) and that seems a strange result cause when I compile the code , it prints out this:
blue = 0
green = 72
red = 45
blue = 255
green = 0
red = 0
Press any key to continue . . .
and the code is :
p_blue = &(img.data[3 *(w*y + x) + 0]);
p_green = &(img.data[3 *(w*y + x) + 1]);
p_red = &(img.data[3 *(w*y + x) + 2]);
printf("blue = %i \n" , *p_blue);
printf("green = %i \n" , *p_green);
printf("red = %i \n" , *p_red);
printf("\n\n");
*p_red = 0;
*p_green = 0;
*p_blue = 255;
printf("blue = %i \n" , *p_blue);
printf("green = %i \n" , *p_green);
printf("red = %i \n" , *p_red);
The problem here is, you're making changes to the local variable red, green, blue. The chages are not reflected inside img.
Instead, get rid of these local variables and directly deal with the pointers, like
p_blue = &(img.data[3 *(w*y + x) + 0]);
p_green = &(img.data[3 *(w*y + x) + 1]);
p_red = &(img.data[3 *(w*y + x) + 3]); //are you sure, this is 3. not 2?
and then, if you do
*p_red = 0;
*p_green = 0;
*p_blue = 255;
it will be reflected in img.
That said, please do not cast the return value of malloc() and family in C.
So I am currently working on a tutorial to implement a very basic raytracer (currently just drawing solid spheres). Said tutorial is located here: http://thingsiamdoing.com/intro-to-ray-tracing/
The tutorial is completely language agnostic and deals only in pseudocode. I attempted to convert this pseudocode into C but have encountered difficulty. My program compiles fine, yet the outputted .ppm image file experiences an early EOF error. The lack of information about the problem has left me stuck.
Here is my C code, which is meant to be a direct translation of the pseudocode:
#include <stdio.h>
#include <math.h>
#define WIDTH 512
#define HEIGHT 512
typedef struct {
float x, y, z;
} vector;
float vectorDot(vector *v1, vector *v2) {
return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z;
}
void writeppm(char *filename, unsigned char *img, int width, int height){
FILE *f;
f = fopen(filename, "w");
fprintf(f, "P6 %d %d %d\n", width, height, 255);
fwrite(img, 3, width*height, f);
fclose(f);
}
float check_ray(px, py, pz, dx, dy, dz, r) {
vector v1 = {px, py, pz};
vector v2 = {dx, dy, dz};
float det, b;
b = -vectorDot(&v1, &v2);
det = b*b - vectorDot(&v1, &v1) + r*r;
if (det<0)
return -1;
det = sqrtf(det);
float t1 = b - det;
float t2 = b + det;
return t1;
}
int main(void) {
int img[WIDTH*HEIGHT*3], distToPlane;
float cameraY, cameraZ, cameraX, pixelWorldX, pixelWorldY, pixelWorldZ, amp, rayX, rayY, rayZ;
for (int px = 0; px<WIDTH; px++) {
for (int py = 0; py<HEIGHT; py++) {
distToPlane = 100;
pixelWorldX = distToPlane;
pixelWorldY = (px - WIDTH / 2) / WIDTH;
pixelWorldZ = (py - HEIGHT / 2) / WIDTH;
rayX = pixelWorldX - cameraX;
rayY = pixelWorldY - cameraY;
rayZ = pixelWorldZ - cameraZ;
amp = 1/sqrtf(rayX*rayX + rayY*rayY + rayZ*rayZ);
rayX *= amp;
rayY *= amp;
rayZ *= amp;
if (check_ray(50, 50, 50, rayX, rayY, rayZ, 50)) {
img[(py + px*WIDTH)*3 + 0] = 0;
img[(py + px*WIDTH)*3 + 1] = 0;
img[(py + px*WIDTH)*3 + 2] = 128;
}
else {
img[(py + px*WIDTH)*3 + 0] = 255;
img[(py + px*WIDTH)*3 + 1] = 255;
img[(py + px*WIDTH)*3 + 2] = 255;
}
}
}
writeppm("image.ppm", "img", WIDTH, HEIGHT);
}
I am fairly confident the error does not lie with my function to write the .ppm file as I have used this for other work and it has been fine.
You may want to remove the quotes from around "img" in the following line of code:
writeppm("image.ppm", "img", WIDTH, HEIGHT);
seeing as how its prototype is void writeppm(char *, unsigned char *, int, int), although I am surprised that your compiler didn't at least give you a warning about a type mismatch.
Also, for the record, I would suggest putting some error checking code (like checking the return value of fwrite, or checking the return value of fopen)--- but that's just me.
Also, if you are not, please compile with all the warning enabled (eg with gcc use -ansi -Wall -pedantic), this will help you catch type mismatches and other little gotcha-ya's
I see two errors in main
int img[WIDTH*HEIGHT*3];
...
writeppm("image.ppm", "img", WIDTH, HEIGHT);
should be
unsigned char img[WIDTH*HEIGHT*3];
...
writeppm("image.ppm", img, WIDTH, HEIGHT);
We know the streight line that mspaint can draw into a picture. Since nested loops fill the whole area (x/y) i was wondering whats the way of doing this. Drawing a line from (x0 y0) of the image to desired x/y. Im using this function for finding the x/y pixel of the bmp:
dword find (FILE* fp, dword xp, dword yp)
{
word bpx = (3*8);
dword offset = (2+sizeof(BMP)+sizeof(DIB));
dword w = 500;
dword row = (((bpx * w) * 4) / 32);
dword pixAddress = (offset) + row * yp + ((xp * bpx) / 8);
return pixAddress;
}
And I've tried with many functions for drawing line from 0x0 to xy, their results are close.. but not entirely.
byte color_pattern[] = { 255, 255, 255 };
dword xy_offset[] = {1, 1};
void bmp_lineto(dword endx, dword endy)
{
int dx = endx - xy_offset[0];
int dy = endy - xy_offset[1];
int twody = 2 * dy;
int twodxdy = 2 * (dy - dx);
int dp = twody - dx;
int X, Y, xEnd, yEnd;
FILE* fp = fopen(convert(FILENAME.text), "rb+");
if(xy_offset[0] > endx)
{
X = endx;
Y = endy;
xEnd = xy_offset[0];
}
else
{
X = xy_offset[0];
Y = xy_offset[1];
xEnd = endx;
}
while(X < xEnd)
{
X = X + 1;
if(dp < 0)
{
dp = dp + twody;
} else { Y = Y + 1; dp = dp + twodxdy;
}
fseek(fp, find(fp, X, Y), SEEK_SET);
fwrite(&color_pattern, 1, 3, fp);
}
}
But the result on the bmp from this code is so... uncertain:
bmp_lineto(200, 230); The entire image is x500 : y460
UPDATED. The y coordinate is same as x. Thats the problem
Take a look at the following code - I adapted this from Rosetta Code
#include <stdio.h>
#include <stdlib.h>
#define NX 40
#define NY 20
typedef unsigned char byte;
typedef struct {
int x;
int y;
} point;
typedef struct{
char M[NX][NY];
} bitmap;
void drawLine(point *a, point*b, bitmap *B, FILE* fp, byte *color_pattern) {
int x0 = a->x, y0 = a->y;
int x1 = b->x, y1 = b->y;
int dx = abs(x1-x0), sx = (x0<x1) ? 1 : -1;
int dy = abs(y1-y0), sy = (y0<y1) ? 1 : -1;
int err = (dx>dy ? dx : -dy)/2, e2;
int index;
while(1){
// the next three lines put the pixel right in the file:
index = (y0 * NX + x0)*3;
fseek(fp, index, SEEK_SET);
fwrite(color_pattern, 1, 3, fp);
B->M[x0][y0]=1; // for code testing
if (x0==x1 && y0==y1) break;
e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
void printLine(bitmap *B){
int ii, jj;
for(ii=0; ii<NY; ii++) {
for(jj=0; jj<NX; jj++) {
printf("%d", (int)B->M[jj][ii]);
}
printf("\n");
}
}
int main(void) {
FILE *fp;
point start = {34,7};
point end = {14, 17};
bitmap B;
byte color[]={255,255,255};
// initialize map to zero. Want to do same with file I suppose
int ii, jj;
for(ii=0; ii<NX; ii++) {
for(jj=0; jj<NY; jj++) {
B.M[ii][jj]=0;
}
}
fp = fopen("mypicture.bmp", "wb");
drawLine(&start, &end, &B, fp, color);
printLine(&B);
fclose(fp);
}
I think it should be easy to adapt it for your situation. Note I have tried to separate / localize variables a little more - that is usually a good idea; there are still many ways to further improve this code (this is a situation where C++ might be a better language...)
Output of the above:
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000001100000
0000000000000000000000000000000110000000
0000000000000000000000000000011000000000
0000000000000000000000000001100000000000
0000000000000000000000000110000000000000
0000000000000000000000011000000000000000
0000000000000000000001100000000000000000
0000000000000000000110000000000000000000
0000000000000000011000000000000000000000
0000000000000001100000000000000000000000
0000000000000010000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
Looks like the "right" line to me... even though it's got the X going in the negative direction. That's the advantage of starting with proven code (in this case, Bresenham's algorithm as implemented on Rosettacode).
You can look into Bresenham's line algorithm. There are extensions to it that handle anti-aliasing too.
I'm doing "photo" processing application using C with OpenCV.
My computer will constantly survey its surroundings using its
webcam. When it detects movement, it will write the current
webcam image to a file (notify).
This is how I have written the code , but it is very slow, I'm not good in doing the notify....could you give me please some good advice concerning the code?
#include <stdio.h>
#include "cv.h"
#include "highgui.h"
#include <dos.h>
#include <conio.h>
CvCapture *capture;
int key;
IplImage *oldFrame;
IplImage *currentFrame;
IplImage *res;
int f=0,x,y,idx,idy;
int currentFrame_width, currentFrame_height;
int oldFrame_width, oldFrame_height;
int res_width, res_height;
int main( int argc, char** argv )
{
while( key != 'q' )
{
capture = cvCaptureFromCAM( 0 );
if( !capture ) return 1;
key = cvWaitKey( 1 );
cvNamedWindow( "FrameController", CV_WINDOW_AUTOSIZE );
if(f==0){
oldFrame = cvQueryFrame( capture );
cvShowImage( "FrameController", oldFrame );
f=1;
}
else{
CvMemStorage* storage = cvCreateMemStorage(0);
currentFrame = cvQueryFrame( capture );
for ( x=0;x<currentFrame->width;x++)
{
for ( y=0;y<currentFrame->height;y++)
{
idx = y*currentFrame->widthStep + currentFrame->nChannels*x;
idy = y*oldFrame->widthStep + oldFrame->nChannels*x;
}
}
uchar R= (uchar) currentFrame->imageData [idx+0];
uchar G = (uchar) currentFrame->imageData [idx+1];
uchar B = (uchar) currentFrame->imageData [idx+2];
uchar R1= (uchar) oldFrame->imageData [idy+0];
uchar G1 = (uchar) oldFrame->imageData [idy+1];
uchar B1 = (uchar) oldFrame->imageData [idy+2];
if(!((R==R1) || (G==G1) || (B==B1))){
f=0;
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "C:\\OpenCV2.1\\data\\haarcascades\\haarcascade_frontalface_alt2.xml" );
double scale = 1.3;
static CvScalar colors[] = {CV_RGB(rand()&255, rand()&255, rand()&255 )};
cvClearMemStorage( storage );
CvSeq* objects = cvHaarDetectObjects( currentFrame, cascade, storage, 1.1, 4, 0, cvSize( 40, 50 ));
CvRect* r;
for( int i = 0; i < (objects ? objects->total : 0 ); i++ ){
r = ( CvRect* )cvGetSeqElem( objects, i );
cvRectangle( currentFrame, cvPoint( r->x, r->y ), cvPoint( r->x + r->width, r->y + r->height ),
colors[i%8]);
cvShowImage( "FrameController", currentFrame );
}
}
}
}
cvDestroyWindow( "FrameController" );
cvReleaseCapture( &capture );
cvReleaseImage( ¤tFrame);
cvReleaseImage( &oldFrame);
return 0;
}
Seems like you're doing unnecessary initializations inside your while loop. For example
capture = cvCaptureFromCAM( 0 ); << is that necessary to be in the loop?
cvNamedWindow( "FrameController", CV_WINDOW_AUTOSIZE ); << this?
for ( x=0;x<currentFrame->width;x++)
{
for ( y=0;y<currentFrame->height;y++)
{
idx = y*currentFrame->widthStep + currentFrame->nChannels*x;
idy = y*oldFrame->widthStep + oldFrame->nChannels*x;
}
} << that's a loop over the WHOLE IMAGE that does NOTHING.
What is the storage used for?
Hope that helped you clean up your code a bit.
Greeting,
I have this graphic homework in BGI graphic. We must use DevCPP and BGI, and matrices.
I wrote this code, and I think the transformations is good. But my triangle doesn't move and rotate around the circle, And I don't understand, why not it moves around the circle...
I don't know where and what I have to rewrite.
#include <math.h>
#include "graphics.h"
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define PI 3.14159265
typedef float Matrix3x3[3][3];
Matrix3x3 theMatrix;
int Round( double n ){
return (int)( n + 0.5 );
}
void matrix3x3SetIdentity(Matrix3x3 m)
{
int i, j;
for(i=0; i<3; i++)
for(j=0; j<3;j++)
m[i][j]=(i==j);
}
/* Multiplies matrix, result in b matrix */
void matrix3x3PreMultiply(Matrix3x3 a, Matrix3x3 b)
{
int r, c;
Matrix3x3 tmp;
for(r=0; r<3;r++)
for(c=0; c<3;c++)
tmp[r][c]=
a[r][0]*b[0][c]+a[r][1]*b[1][c]+a[r][2]*b[2][c];
for(r=0; r<3;r++)
for(c=0; c<3; c++)
b[r][c]-tmp[r][c];
}
void translate2(int tx, int ty)
{
Matrix3x3 m;
matrix3x3SetIdentity (m);
m[0][2] = tx;
m[1][2] = ty;
matrix3x3PreMultiply(m, theMatrix);
}
void scale2 (float sx, float sy, pont2d refpt)
{
Matrix3x3 m;
matrix3x3SetIdentity(m);
m[0][0]=sx;
m[0][2]=(1-sx)*refpt.x;
m[1][1]=sy;
m[1][2]=(1-sy)*refpt.y;
matrix3x3PreMultiply(m, theMatrix);
}
void rotate2 (float a, pont2d refpt)
{
Matrix3x3 m;
matrix3x3SetIdentity(m);
a=a/PI;
m[0][0] = cosf(a);
m[0][1] = -sinf(a);
m[0][2] = refpt.x * (1-cosf(a)) + refpt.y * sinf(a);
m[1][0] = sinf (a);
m[1][1] = cosf (a);
m[1][2] = refpt.y * (1-cosf(a)) - refpt.x * sinf(a);
matrix3x3PreMultiply(m, theMatrix);
}
void transformPoints2 (int npts, pont2d *pts)
{
int k;
float tmp;
for (k = 0; k < npts; k++) {
tmp = theMatrix[0][0] * pts[k].x + theMatrix[0][1] *
pts[k].y + theMatrix[0][2];
pts[k].y = theMatrix[1][0] * pts[k].x + theMatrix[1][1] *
pts[k].y + theMatrix[1][2];
pts[k].x = tmp;
}
}
int main()
{
int gd, gm, i, page=0;
gd=VGA;gm=VGAHI;
initgraph(&gd,&gm,"");
int ap;
while(!kbhit())
{
setactivepage(page);
cleardevice();
pont2d P[3] = { 50.0, 50.0, 150.0, 50.0, 100.0, 150.0};
pont2d refPt = {200.0, 250.0};
// Drawing the Triangle
moveto( Round( P[ 0 ].x ), Round( P[ 0 ].y ) );
for( i = 1; i < 3; i++ )
lineto( Round( P[ i ].x ), Round( P[ i ].y ) );
lineto( Round( P[ 0 ].x ), Round( P[ 0 ].y ) );
// Drawing the Circle
fillellipse(200, 250, 5,5);
setcolor (BLUE);
matrix3x3SetIdentity (theMatrix);
scale2 (0.5, 0.5, refPt);
//scale2 (20, 20, refPt);
rotate2 (90.0, refPt);
translate2 (0, 150);
transformPoints2 (3, P);
setvisualpage(page);
page = 1-page;
}
getch();
closegraph();
return 0;
}
If you want to see the object "spin", then rotations should be performed about the local origin. Rotation about the global origin will cause the object to "orbit" the global origin. Thus, to spin the object:
Translate the object to global origin
Apply the rotation
Translate the object back to its original position
Look at the discussion regarding transformation order here for an illustration. Specifically, look for the section entitled "Demonstration of the importance of transformation order".
To rotate a triangle, get the three points and use the formula:
x' = x + r cos (theta)
y' = y - r sin (theta)
The above formula can be applied into a loop where there being 0 to 360. You can have a graphics simulation by putting a delay (200) milliseconds in the loop.