📄 bezier.c
字号:
#define byte unsigned char
#define word unsigned short
#include <stdlib.h>
#include <stdio.h>
#include "metawndo.h" /* master MetaWINDOW include file */
/* special stack size declaration if using Turbo or Borland C++ */
#ifdef TurboC
extern unsigned _stklen = 14336U; /* stack size 14K */
#endif
void DrawBezier( point *bez, int count );
void DrawHandle( point *bez, int count, int control );
void Waiting(int a);
#define HANDLESIZE 10 // size of 'handle' bounding boxes
#define NUMPOINTS 16 // number of points in our sample array
void bezier( )
{
#ifdef _MNT_
void QueryMousePosition(int *x, int *y, int *level, int *button);
#endif
void quit(void);
int GrafixCard = 2;
rect scrnR, tR;
point mousePt, bz[NUMPOINTS];
mwEvent myevent;
int i, x, y, l, buttons;
/* init the system */
// i = InitGraphics( GrafixCard );
// SetDisplay( GrafPg0 );
/* set a virtual coordinate system of 500x500 */
SetRect( &scrnR, 0, 0, 500, 500 );
VirtualRect( &scrnR );
// Init the bezier control points
bz[0].X=25; bz[0].Y=475;
bz[3].X=125; bz[3].Y=25;
bz[6].X=250; bz[6].Y=450;
bz[9].X=375; bz[9].Y=25;
bz[12].X=475; bz[12].Y=475;
bz[15].X=33; bz[15].Y=475;
// Init bezier handles
bz[1].X=13; bz[1].Y=425; // handle from point 0
bz[2].X=75; bz[2].Y=25; // handle to point 3
bz[4].X=225; bz[4].Y=45; // handle from point 3
bz[5].X=150; bz[5].Y=450; // handle to point 6
bz[7].X=350; bz[7].Y=425; // handle from point 6
bz[8].X=275; bz[8].Y=5; // handle to point 9
bz[10].X=425; bz[10].Y=25; // handle from point 9
bz[11].X=485; bz[11].Y=425; // handle to point 12
bz[13].X=463; bz[13].Y=488; // handle from point 12
bz[14].X=38; bz[14].Y=488; // handle to point 15
DrawBezier( bz, NUMPOINTS );
// let them move the points around
TrackCursor( 1 );
#ifndef CYCLE
// until a key is pressed
while( 1 ) {
MoveTo( (scrnR.Xmax >> 1),scrnR.Ymax - 30 );
DrawString( "Use mouse to move control points" );
MoveTo( (scrnR.Xmax >> 1),scrnR.Ymax - 20 );
DrawString( "Or press 'x' to exit" );
MoveTo( (scrnR.Xmax >> 1),scrnR.Ymax - 10 );
DrawString( "any other key to continue" );
KeyEvent( 1, &myevent );
/* key press is exit */
if( myevent.eventType == evntKEYDN )
break;
/* we only care about mouse button press events */
if( myevent.eventType != evntPRESS )
continue;
// is press on a bezier point ?
mousePt.X = myevent.eventX;
mousePt.Y = myevent.eventY;
Gbl2VirPt(&mousePt);
for( i = 0 ; i < NUMPOINTS; i++ ) {
CenterRect( &bz[i], HANDLESIZE, HANDLESIZE, &tR );
if( PtInRoundRect( &mousePt, &tR, 2, 2, 2, 2 ) )
break;
}
// not on any of our points, keep trying
if( i >= NUMPOINTS )
continue;
// drag a bezier point
buttons = myevent.eventButtons;
while( buttons ) {
// wait for a movement
#ifdef _MNT_
QueryMousePosition(&x,&y,&l,&buttons);
#else
/* This is a raw Metagraphics function */
QueryCursor(&x,&y,&l,&buttons);
#endif
if( x == myevent.eventX && y == myevent.eventY )
continue;
// record new position
myevent.eventX = x; myevent.eventY = y;
// first undraw it
DrawHandle( bz, NUMPOINTS, i );
// change the point
bz[i].X = x;
bz[i].Y = y;
Gbl2VirPt(&bz[i]);
// re-draw it
DrawHandle( bz, NUMPOINTS, i );
} // end of while(buttons)
// redraw the updated curve
DrawBezier( bz, NUMPOINTS );
} // end of while( 1 )
if((myevent.eventChar == 'x') || (myevent.eventChar == 'X')) quit();
#else
#ifdef _MNT_
KeyEvent(0, &myevent);
if((myevent.eventChar == 'x') || (myevent.eventChar == 'X')) quit();
#endif
Waiting(150);
#endif
SetLocal();
return;
}
// update the display to show the Bezier curve with indicators
void DrawBezier( point *bez, int count )
{
int i;
rect scrnR;
HideCursor();
ScreenRect( &scrnR );
BackColor( LtBlue );
EraseRect( &scrnR );
PenColor( Green );
PaintBezier( bez, count );
PenColor( Red );
PolyBezier( bez, count );
PenSize(4,4);
PenShape(shapeOval);
FrameBezier( bez, count );
PenNormal();
// show all the points and handles
for( i = 0 ; i < count; i += 3 )
DrawHandle( bez, count, i );
ShowCursor();
}
// givin a bezier point, draw indicators for its associated control and
// handle points
void DrawHandle( point *bez, int count, int pointndx )
{
int control;
rect tR;
HideCursor();
// draw in invert
PenColor( -1 );
RasterOp( zXORz );
// compute the control point index (second of each three points)
control = (pointndx + 1) / 3 * 3;
// center a rectangle on the bezier control point
CenterRect( &bez[control], HANDLESIZE, HANDLESIZE, &tR );
// draw an oval for the first point
/* FrameOval( &tR ); */
MarkerSize(HANDLESIZE, HANDLESIZE);
MarkerAngle((control << 8));
MarkerType((short) control);
PolyMarker(1, &bez[control]);
// draw on the preceeding handle (if any)
if( control != 0 ) {
CenterRect( &bez[control-1], HANDLESIZE, HANDLESIZE, &tR );
FrameRect( &tR );
MoveTo( bez[control].X, bez[control].Y );
LineTo( bez[control-1].X, bez[control-1].Y );
}
// center a rectangle on the postceeding handle (if any)
if( control < (count - 1) ) {
CenterRect( &bez[control+1], HANDLESIZE, HANDLESIZE, &tR );
FrameRect( &tR );
MoveTo( bez[control].X, bez[control].Y );
LineTo( bez[control+1].X, bez[control+1].Y );
}
RasterOp( zREPz );
ShowCursor();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -