📄 mirrors.asm
字号:
;------------------------------------------------------------
; Mirrors
; -------
;
; Orthogonal circle creation and circle inversion demo
; ----------------------------------------------------
;
; The program creates several orthogonal circles around a base circle.
; Each orthogonal circle is then used as a mirror circle to mathematically
; invert (reflect) all the other orthogonal circles. This creates more
; orthogonal circles and the process is repeated a second time on these new
; circles to extend the set of orthogonal circles and thereby build a
; beautiful graphic.
; by Ron Thomas 30/7/99
;
; Ron_Thom@Compuserve.com & www.rbtmomas.freeserve.co.uk
;-------------------------------------------------------------
.386 ; 32 bit when .386 appears before .MODEL
.model flat,stdcall
include windows.inc
include user32.inc
include kernel32.inc
include gdi32.inc
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
WinMain PROTO :DWORD, :DWORD, :DWORD, :SDWORD
.data
ClassName db "SimpleWinClass",0
AppName db "It's all done by mirrors !",0
; **** To change the model alter the variables NOC and NoLevels as required.
; ---------------------------------------------------------------------
NoLevels EQU 2 ; Nesting level for circle inversion
NOC EQU 5 ; No of orthogonal circles to be built around the base circle
; valid for 2 to 10 circles only.
Total_no_circles EQU (1 + NOC + NOC*(NOC-1) + NOC*(NOC-1)*(NOC*(NOC-1)-1))
; Above 4 terms are only for 2 of levels inversion
; e.g for 4 initial orthogonals & 2 levels we get: 1 + 4 + 4*3 + 4*3*11 = 149
; The 3rd level is a little impractical at 17590 circles !
; Beyond that the number is too many to consider !!
deg2rad DQ 3f91df46a2529d39h ; 2 * pi / 360 (conversion factor for radians)
count dw 1 ; Controls inversion nesting; 1 gives 2 levels, 2 gives 3 etc
first DD 16 ; Index to first circle to be inverted
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
; Set up a structure to hold data for all created circles
; Floating point numbers are used so that precision is not lost by
; rounding action as in the case of integer computation of radii etc
Circle$ STRUCT 4 ; Align for fastest speed
X_Coord real4 ? ; X and Y coordinates for the circle centre
Y_Coord real4 ? ;
Radius real4 ? ; Radius
Colour DD ? ; Circle colour
Circle$ ENDS ; End of circle structure
circles Circle$ Total_no_circles DUP ({}) ; Provide storage for circle data
base_circle_diameter real4 ?
delta_X real4 ?
delta_Y real4 ? ; Storage for computational constants
first_orthog_Y real4 ? ; Computed value for 1st orthog circle (Y coord)
sin_beta real4 ? ;
cos_beta real4 ? ;
SL_prime real4 ? ;
SM_prime real4 ? ;
radius_cos_beta real4 ? ; radius*cos(beta)
radius_sin_beta real4 ? ; radius*sin(beta)
theta real4 ? ; Required rotation in degrees
math_X_Coord real4 ? ;
math_Y_Coord real4 ? ; Math space coordinates
hdc HDC ?
cxClient DD ?
cyClient DD ?
bluepen DD ? ; Pen handle
x1 DD ?
x2 DD ?
y1 DD ?
y2 DD ?
temp DD ? ; Temporary variable
last DD ? ; " last " " "
circles_made DD ? ; (No of circles made by inversion)*4
.const
frac_screen real4 0.666666 ; Set base circle to this fraction of cyClient
two real4 2.0E0
; Arbitrary factor used to derive 1st orthog Y coord, adjust if necessary for your system
Pfact real4 1.0,1.0,5.0,2.002,1.417,1.238,1.156,1.112,1.085,1.066,1.054
;-------------------------------------------------------------------------------------------
;Macros
LOWORD MACRO bigword ;; Retrieves the low word from double word argument
mov eax,bigword
and eax,0FFFFh ;; Set to low word
ENDM
HIWORD MACRO bigword ;; Retrieves the high word from double word argument
mov ebx,bigword
shr ebx,16 ;; Shift 16 for high word to set to high word
ENDM
RGB MACRO red, green, blue ;; Get composite number from red green and blue bytes
mov al,blue ;; ,,,blue
shl eax,8 ;; ,,blue,
add al,green ;; ,,blue,green
shl eax,8 ;; ,blue,green,
add al,red ;; ,blue,green,red
and eax,0FFFFFFh ;; Mask out top byte to complete COLORREF dword
ENDM
CIRCLE MACRO xc,yc,rad, col ;; x & y centre coords, the radius and the colour
fld xc
fsub rad
fistp x1 ;; x1 boundary
fld yc
fsub rad
fistp y1 ;; y1 boundary
fld xc
fadd rad
fistp x2 ;; x2 boundary
fld yc
fadd rad
fistp y2 ;; y2 boundary
invoke SelectObject, hdc, col
invoke Ellipse, hdc, x1, y1, x2, y2 ; Fill circle with colour
ENDM
CIRCLECOLOUR MACRO red,green,blue, n ;; Set initial orthogonal circle colours
RGB red, green, blue ;; Set RGB colour
invoke CreateSolidBrush, eax
mov circles.Colour[n*16],eax
ENDM
;----------------------------------------------------------------------------
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,0
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
INVOKE UpdateWindow, hwnd
.WHILE TRUE
INVOKE GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc uses ebx esi edi, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL ps:PAINTSTRUCT, msg:MSG
mov eax,uMsg
.IF eax==WM_CREATE
finit ; Initialise coprocessor
invoke CreatePen, PS_SOLID, 1, 0FF0000h ; Solid, thin & blue
mov bluepen,eax
;-------------------------------------------------------------------------
; Set some colours for the orthogonal circles around the base circle (10 are set)
;-------------------------------------------------------------------------
CIRCLECOLOUR 255, 0, 0, 1 ; Red
CIRCLECOLOUR 0, 255, 255, 2 ; Cyan
CIRCLECOLOUR 0, 0, 255, 3 ; Blue
CIRCLECOLOUR 255, 0, 255, 4 ; Magenta
CIRCLECOLOUR 255, 255, 0, 5 ; Yellow
CIRCLECOLOUR 0, 255, 0, 6 ; Green
CIRCLECOLOUR 255, 0, 125, 7
CIRCLECOLOUR 128, 255, 128, 8
CIRCLECOLOUR 255, 128, 128, 9
CIRCLECOLOUR 128, 128, 255, 10 ; Extend if more orthogonal circles are to be
; created about the base circle
.ELSEIF eax==WM_SIZE
LOWORD lParam
mov cxClient,eax
shr eax,1
mov temp,eax
fild temp
fstp circles.X_Coord ; save base X-centre coord
HIWORD lParam
mov cyClient,ebx
shr ebx,1
mov temp,ebx
fild temp
fst circles.Y_Coord ; save base Y-centre coord
fmul frac_screen ; Set R(b) to fraction (2/3) of max possible
fst circles.Radius ; save radius
fmul two
fstp base_circle_diameter
fild cyClient
fdiv two
fld circles.Radius ; get base radius
mov ebx,NOC
shl ebx,2 ; *4
fmul Pfact[ebx] ; mult by abitrary factor (alter as required)
fsub ; & subtract to
fstp first_orthog_Y ; get Y centre for 1st orthog circle
mov first,16 ; Reset these if we have to redraw
mov count,1 ;
mov circles_made,0 ;
.ELSEIF eax==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
; Set the 4 boundaries and draw the base circle
invoke SelectObject, hdc, bluepen
; mov esi,0 ; Make sure its zero
CIRCLE circles.X_Coord, circles.Y_Coord, circles.Radius, 0
;---------------------------------------;
; Build 1st orthogonal circle ;
;---------------------------------------;
fld circles.X_Coord ; Start with a circle vertically above the base circle
fstp circles.X_Coord[16] ; Set X coord for centre of 1st orthogonal circle
fld first_orthog_Y ; Arbitrary value; changes appearance of the graphic
fstp circles.Y_Coord[16] ; Store Y coord
; Calculate the angle necessary to rotate the orthogonal circles
; centre and obtain the sequence of symetrically placed circles
mov temp,360
fild temp ; Set 360 degrees into st
mov temp,NOC ; # circles orthogonal to the base circle
fild temp ;
fdiv ; get reqd angle in degrees
fstp theta ;
mov ebx,1*16 ; esi is an index to the circles
; Calculate P, which is the distance from the new centre to the
; circumference of the base circle, (on a line joining the two centres),
; using the equation:
; P = -R(b) + SQRT( ((X(n)-X(b))**2 + ((Y(n)-Y(b))**2 )
; where R(b) is the radius of the base circle
; X(b) is the X coordinate of the base circle
; Y(b) Y " " "
; X(n) X " " orthogonal circle
; Y(n) Y " " " "
fld circles.X_Coord[ebx] ; Get difference in X coordinates
fsub circles.X_Coord ; X(n) - X(b)
fld st ; Push copy onto the stack (in st(1))
fmul ; we have delta_X squared
fld circles.Y_Coord[ebx] ; Get difference in Y coordinates
fsub circles.Y_Coord ; Y(n) - Y(b)
fld st ; Take copy
fmul ; delta_Y squared
fadd ; Add the squares
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -