📄 invcircs.asm
字号:
mov eax,y1
add eax,y2
mov temp,eax
fild temp
fdiv two
fstp circles.Y_Coord[ebx] ; circle-centre y-coord
mov eax,cDiam
mov temp,eax
fild temp
fdiv two
fstp circles.Fradius[ebx] ; save radius as FP number
mov eax,cDiam ; Incr x1 boundary for next circle in row
add x1,eax
add ebx,16 ; increment the circle index
inc esi
.ENDW
mov eax,cDiam
add y1,eax ; Set new y1 boundary
inc edi
.ENDW
.WHILE !inverted ; Loop until key-hit when we invert the circles
invoke PeekMessage, ADDR msg, hWnd, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE
.IF eax!=0
.BREAK ; Escape loop if we detect a keypress
.ENDIF
.ENDW
invoke GetStockObject, WHITE_BRUSH
mov whiteBrush,eax
invoke SelectObject, hdc, eax
invoke Rectangle, hdc, 0, 0, cxClient, cyClient ; Clear the screen
;***********************************************;
; Now invert all circles in the array ;
;***********************************************;
mov last,bx ; bx is the index to ALL circles
sub last,16
mov di,first ; Set index to 1st target circle
.WHILE di <= last ; Loop until all targets are inverted
;-------------------------------------------------------------------------;
; Calculate the angle beta between the line joining the centres of the ;
; inversion circle & the target circle to be inverted, & the horizontal ;
; also evaluate the sine and cosine. ;
;-------------------------------------------------------------------------;
fld circles[0].Y_Coord ; Y coord for inversion circle
fsub circles[di].Y_Coord ; Get delta_Y into st
fld circles[0].X_Coord
fsub circles[di].X_Coord ; Now st = delta_X, st1 = delta_y
fpatan ; Get the angle in radians
fsincos ; Get sine & cosine
fxch ; Swap sine & cosine
fstp sin_beta ; save sin(beta) & pop
fst cos_beta ; save cos(beta)
;-------------------------------------------------------------------------;
; Calculate distance "SL" between the centre "S" of the invertion circle ;
; and the most distant point "L" on the circumference of target circle ;
; which is coincident with the line joining the 2 centres. ;
; ;
; We use the equation:- ;
; ;
; SL = SQRT( (X(m) - X(t) + R(t)*cos(beta) )**2 + ;
; (Y(m) - Y(t) + R(t)*sin(beta) )**2 ) ;
; ;
; where X(m),Y(m) are the coordinates for centre of the invertion circle;
; X(t),Y(t) " " " " target " ;
; R(t) is the radius of the target circle ;
;-------------------------------------------------------------------------;
fmul circles[di].Fradius ; Times radius of the target circle
fst radius_cos_beta ; st = R*cos(beta)
fld circles[0].X_Coord ; Get invertion circles X coordinate
fsub circles[di].X_Coord ; Minus target circles X coordinate
; Gives X(m) - X(t)
; st = delta_X, st(1) = R*cos(beta)
fst delta_X ; Save for use again
fadd ; st = X(m) - X(t) + R(t)*cos(beta)
fld st ; Take a copy into st(1)
fmul ; Square=(X(m)-X(t)+R(t)*cos(beta))^2
fld sin_beta ; st = sin(beta),st(1)=term1^2
fmul circles[di].Fradius
fst radius_sin_beta ; Save for use again
fld circles[0].Y_Coord ; Get invertion circle Y coordinate
fsub circles[di].Y_Coord ; Minus target circles Y coordinate
; Gives Y(m) - Y(t)
; st=delta_Y, st(1)=R*sin(beta),st(2)=term1^2
fst delta_Y
fadd ; st=Y(m)-Y(t)+R(t)*sin(beta),st(1)=term1^2
fld st ; Take a copy into st(1)
fmul ; and form the square
; st=term2^2, st(1)=term1^2
fadd ; Add the 2 squares togeter
fsqrt ; Now have SL in st(0)
;--------------------------------------------------------------------------;
; In circle inversion we have the relationship:- ;
; ;
; SQ * SQ' = R**2 ;
; ;
; where SQ is the distance from the centre of the base circle to ;
; any radial point within it. ;
; SQ' is the distance from the centre of the base circle to ;
; the inverted point on the same radial line. ;
; R is the radius of the mirror circle. ;
; ;
; We therefore calculate the distance SL' using the equation:- ;
; ;
; SL' = R(m)**2/SL ;
;--------------------------------------------------------------------------;
fld circles[0].Fradius ; Load radius of invertion circle
fld st ; Take a copy
fmul ; Square it to give st=R^2,st(1)=SL
fld st ; Take a copy; R^2, R^2, SL
fdiv st,st(2) ; Divide by SL; SL', R^2, SL
fstp SL_prime ; Store SL'; R^2, SL
fxch ; Swap; st=SL, st(1)=R^2
fstp st ; Flush st st=R^2
;--------------------------------------------------------------------------;
; Calculate distance "SM" between the centre of the invertion circle and ;
; the nearest point "M" on the circumference of the target circle, which ;
; is coincident with the line joining the 2 centres. We use equation:- ;
; ;
; SM = SQRT( (X(m) - X(t) - R(t)*cos(beta) )**2 + ;
; (Y(m) - Y(t) - R(t)*sin(beta) )**2 ) ;
; ;
; where X(m),Y(m) are the coordinates for centre of the invertion circle ;
; X(t),Y(t) " " " " target " ;
; R(t) is the radius of the target circle ;
;--------------------------------------------------------------------------;
fld delta_X ; st = delta_X, st(1) = R^2
fsub radius_cos_beta ; st = X(m)-X(t)-R(t)*cos(beta), st(1)=R^2
fld st ; Take a copy
fmul ; Square; term1^2, R^2
fld delta_Y ; st = delta_Y, st(1)=term1^2, st(2)=R^2
fsub radius_sin_beta ; Y(m)-Y(t)-R(t)*sin(beta), term1^2,R^2
fld st ; Take a copy
fmul ; Square; term2^2, term1^2, R^2
fadd ; Add the 2 squares togeter
fsqrt ; Now have SM in st(0) & R^2 in st(1)
; Calculate the distance SM' using the equation: SM' = R(m)**2/SM
fdiv ; Divide R**2 by SM to give SM'
fst SM_prime
fld st ; Take a copy; SM', SM'
; Then the radius of the inverted circle is given by (SM' - SL')/2
fsub SL_prime ; st = (SM' - SL'), st(1) = SM'
fabs ; Make sure it's never negative
fdiv two
fstp circles[bx].Fradius ; Add inverted circle to list of radii; now st = SM'
;------------------------------------------------------------------------;
; Now calculate the location of the centre of the inverted circle using ;
; the equations:- ;
; ;
; X(i) = X(m) - (SL' + SM')*cos(beta)/2 ;
; Y(i) = Y(m) - (SL' + SM')*sin(beta)/2 ;
; ;
; where X(i),Y(i) are the coords of the inverted circles centre ;
; ;
;------------------------------------------------------------------------;
fadd SL_prime ; st = (SL' + SM')
fld st ; Take a copy into st(1)
fmul cos_beta ; st=(SL'+SM')*cos(beta), st(1)=(SL'+SM')
fld circles[0].X_Coord
fadd st,st ; Double invertion circles X coordinate
;
fsubr ; X(m)*2-(SL'+SM')*cos(beta),(SL'+SM')
fistp XC ; Store (X coordinate)*2 and get
; (SL' + SM') into st(0)
fwait
shr XC,1 ; Y coord=X(m)-(SL'+SM')*cos(beta)/2
fild XC
fstp circles[bx].X_Coord ; Store X coord't for possible future
; inversion of the created circle
fmul sin_beta ; st = (SL' + SM')*sin(beta)
fld circles[0].Y_Coord ; Get invertion circles Y coordinate
fadd st,st ; Double, st = Y(m)*2, st1=(SL'+SM')..
fsubr ; Y(m)*2 - (SL' + SM')*sin(beta)
fistp YC ; Store & pop stack
fwait
shr YC,1 ; Y coord=Y(m) -(SL'+SM')*sin(beta)/2
fild YC
fstp circles[bx].Y_Coord ; Store Y coord't for possible future
; inversion of the created circle
; Set colour of the inverted circle
mov eax,circles[di].Ccolour ; Get colour of target circle
mov colour,eax ; and set inveted circle to have the same
; Check size of inverted circle
fld circles[bx].Fradius
fistp temp
; cmp temp,3 ; Min circle diameter set to 6 pixels
; jle skip_circle
cmp temp,80 ; Limit size of drawn circle <160 OK
jg skip_circle
; Set the 4 boundaries and fill the inverted circles
fld circles.X_Coord[bx]
fsub circles.Fradius[bx]
fistp x1 ; x1 boundary
fld circles.Y_Coord[bx]
fsub circles.Fradius[bx]
fistp y1 ; y1 boundary
fld circles.X_Coord[bx]
fadd circles.Fradius[bx]
fistp x2 ; x2 boundary
fld circles.Y_Coord[bx]
fadd circles.Fradius[bx]
fistp y2 ; y2 boundary
invoke SelectObject, hdc, colour
invoke Ellipse, hdc, x1, y1, x2, y2 ; Fill circle with colour
add bx,16 ; Bump index up ready for next circle
add circles_made,16 ; Add 16 for each circle
skip_circle:
add di,16
.ENDW
;-------End of circle inversion code----------------
inverted = TRUE
invoke EndPaint,hWnd, ADDR ps
.ELSEIF eax==WM_QUIT
invoke PostMessageA,hWnd,WM_CLOSE,0,0
ret
.ELSEIF eax==WM_DESTROY
invoke DeleteObject, whiteBrush
invoke PostQuitMessage,NULL
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -