|
-
Jul 25th, 2010, 04:13 PM
#1
Thread Starter
Fanatic Member
Making a round rectangle from scratch
If you're curious about sine and cosine(they're not pronounced sin and cos, btw) Google it. I'm not a math teacher, and it's really not that difficult, but you should practice to get the hang of using them.
Create a new project, paste this into it:
vb Code:
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long
Private Const Pi As Double = 3.1415926535898
Private Sub RoundRect(ByVal targetDC As Long, X1 As Long, Y1 As Long, X2 As Long, Y2 As Long, Radius As Double)
'assumes x1 < x2 and y1 < y2, and radius < half either width/height
Dim i As Double 'variable for radians
Dim s As Double 'step
Dim c As Double 'complexity(number of points on the 'circle')
Dim x As Double, y As Double 'spatial coordinates, origin center
Dim Width As Double, Height As Double
Dim RPnts() As POINTAPI 'stores the points of the polygon, ubound should always(post loop) result to c + 1
Dim bc As Long, cc As Long, dc As Long 'counters for corners
ReDim RPnts(0) 'init first index
c = Pi * Radius 'accuracy(sides); lower this and the results could be off, increase if you encounter issues(skewed result)
If c < 28 Then c = 28 'minimal quality; 28 points = 7 per corner
If c > 100 Then c = 100 'max points('sides'), 25 per corner
'this is a simple attempt at adapative accuracy, it's not 'fully tested' the min and max should prevent any GDI problems
s = (2# * Pi) / (c) '1 full circle(2pi) / complexity
'calculate width and height, halved('radius')
Width = (X2 - X1) / 2
Height = (Y2 - Y1) / 2
'point 1 should be less than 2
If Width < 0 Or Height < 0 Then Err.Raise 1
'radius should not exceed either of these
If Radius > Width Or Radius > Height Then Err.Raise 1
'adjust width and height, knowing values are good
Width = Width - Radius
Height = Height - Radius
'assign x, y to 'center point'(origin, the circle's middle)
x = (X1 + X2) / 2
y = (Y1 + Y2) / 2
For i = -Pi To Pi Step s
If i < (-Pi / 2) Then
RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x - Width
RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y - Height
ElseIf i >= (-Pi / 2) And i < 0 Then
RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x + Width
RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y - Height
ElseIf i >= 0 And i < (Pi / 2) Then
RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x + Width
RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y + Height
ElseIf i >= (Pi / 2) Then
RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x - Width
RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y + Height
End If
ReDim Preserve RPnts(UBound(RPnts) + 1)
Next
'draw the result using Polygon(could convert pointAPI to pointF and use GDI+(AA) here instead)
Polygon targetDC, RPnts(0), UBound(RPnts) - 1
End Sub
Private Sub Form_Click()
RoundRect Form1.hdc, 0, 0, 100, 100, 100 'a circle, try complexity(c) of 8 for an octagon
RoundRect Form1.hdc, 0, 100, 300, 200, 5 'a big rectangle
End Sub
Click anywhere on the form. 
Code could be MUCH better. But it's presented here in what I think is the easiest to learn format.
What would make it better:
- Make a loop for each corner OR...
- Create a LUT for the COS/SIN functions
- GDI+ can do floating-point(POINTF) anti-aliased(smoothing mode bicubic) polygons
- Could probably figure out a better adaptive routine if you gave it a whirl
- Then of course things like filling
- You could even reuse just one quadrant, mirroring/flipping for the other corners(if you're considering a manual fill), otherwise GDI+ offers lot of fill(and other) options
Software I use and highly recommend: Opera, Miranda IM, Peerblock, Winamp, Unlocker Assistant, JoyToKey, Virtual CloneDrive, Secunia PSI, ExplorerXP, GOM Player, Real Alternative, Quicktime Alternative,Sumatra PDF, and non-freeware: Photoshop and VB6( ).
My codebank: AllRGB, Rounded Rectangle(math), Binary Server, Buddy Paint, LoadPictureGDI+, System GUID/Volume Serial, HexToAsc, List all processes and their paths, quasiString matching
Strings(search, extraction, retrieval etc): Retrieve BBCode Link from HTML, RemoveBetween ()'s, strFindBetween(str1,str2), Insert text in HTML, HTML - GetSpanByID
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|