### Author Topic: Curve Smoother  (Read 3281 times)

0 Members and 1 Guest are viewing this topic.

#### The Librarian

• Moderator
• Newbie
• Posts: 42 ##### Curve Smoother
« on: March 17, 2018, 01:08:19 AM »
Curve Smoother

Author: @STxAxTIC @FellippeHeitor
Source: Submission
Version: 2014
Tags: [graphics], [relaxation algorithm], [anti-aliasing]

Description:
This program demonstrates (i) linear interpolation to create a curve between points, (ii) a relaxation algorithm to "smooth over" a curve to remove sharp edges, and (iii) plotting with anti-aliasing.

Source code:
Code: QB64: [Select]
1. ' Display
2. SCREEN _NEWIMAGE(800, 600, 32)
3. _SCREENMOVE (_DESKTOPWIDTH \ 2 - _WIDTH \ 2) - 3, (_DESKTOPHEIGHT \ 2 - _HEIGHT \ 2) - 29
4. _TITLE "If these curves were smoother they'd steal your wife."
5.
6. ' Meta
7. start:
8.
9. ' Data structures
10. TYPE Vector
11.
12. ' Object type
13. TYPE Object
14.     Elements AS INTEGER
15.     Shade AS _UNSIGNED LONG
16.
17. ' Object storage
18. DIM SHARED Shape(300) AS Object
19. DIM SHARED PointChain(300, 500) AS Vector
20. DIM SHARED TempChain(300, 500) AS Vector
21. DIM SHARED ShapeCount AS INTEGER
22. DIM SHARED SelectedShape AS INTEGER
23.
24. ' Initialize
25. ShapeCount = 0
26.
27. ' Main loop
28.     IF (UserInput = -1) THEN GOTO start
29.     CALL Graphics
30.     _LIMIT 120
31.
32.
33. FUNCTION UserInput
34.     TheReturn = 0
35.     ' Keyboard input
36.     kk = _KEYHIT
37.         CASE 32
38.             CALL NewMouseShape(7.5, 150, 15)
39.     IF (kk) THEN
40.     UserInput = TheReturn
41.
42. SUB Graphics
43.     LINE (0, 0)-(_WIDTH, _HEIGHT), _RGBA(0, 0, 0, 200), BF
44.     CALL cprintstring(16 * 17, "PRESS SPACE and then drag MOUSE 1 to draw a new shape.")
45.     FOR ShapeIndex = 1 TO ShapeCount
46.         FOR i = 1 TO Shape(ShapeIndex).Elements - 1
47.             CALL lineSmooth(PointChain(ShapeIndex, i).x, PointChain(ShapeIndex, i).y, PointChain(ShapeIndex, i + 1).x, PointChain(ShapeIndex, i + 1).y, Shape(ShapeIndex).Shade)
48.
49. SUB NewMouseShape (rawresolution AS DOUBLE, targetpoints AS INTEGER, smoothiterations AS INTEGER)
50.     ShapeCount = ShapeCount + 1
51.     numpoints = 0
52.     xold = 999 ^ 999
53.     yold = 999 ^ 999
54.             x = _MOUSEX
55.             y = _MOUSEY
56.             IF (x > 0) AND (x < _WIDTH) AND (y > 0) AND (y < _HEIGHT) THEN
57.                     x = x - (_WIDTH / 2)
58.                     y = -y + (_HEIGHT / 2)
59.                     delta = SQR((x - xold) ^ 2 + (y - yold) ^ 2)
60.                     IF (delta > rawresolution) AND (numpoints < targetpoints - 1) THEN
61.                         numpoints = numpoints + 1
62.                         PointChain(ShapeCount, numpoints).x = x
63.                         PointChain(ShapeCount, numpoints).y = y
64.                         CALL cpset(x, y, _RGB(0, 255, 255))
65.                         xold = x
66.                         yold = y
67.     LOOP UNTIL NOT _MOUSEBUTTON(1) AND (numpoints > 1)
68.
69.     DO WHILE (numpoints < targetpoints)
70.         rad2max = -1
71.         kmax = -1
72.         FOR k = 1 TO numpoints - 1
73.             xfac = PointChain(ShapeCount, k).x - PointChain(ShapeCount, k + 1).x
74.             yfac = PointChain(ShapeCount, k).y - PointChain(ShapeCount, k + 1).y
75.             rad2 = xfac ^ 2 + yfac ^ 2
76.             IF rad2 > rad2max THEN
77.                 kmax = k
78.                 rad2max = rad2
79.         FOR j = numpoints TO kmax + 1 STEP -1
80.             PointChain(ShapeCount, j + 1).x = PointChain(ShapeCount, j).x
81.             PointChain(ShapeCount, j + 1).y = PointChain(ShapeCount, j).y
82.         PointChain(ShapeCount, kmax + 1).x = (1 / 2) * (PointChain(ShapeCount, kmax).x + PointChain(ShapeCount, kmax + 2).x)
83.         PointChain(ShapeCount, kmax + 1).y = (1 / 2) * (PointChain(ShapeCount, kmax).y + PointChain(ShapeCount, kmax + 2).y)
84.         numpoints = numpoints + 1
85.
86.     FOR j = 1 TO smoothiterations
87.         FOR k = 2 TO numpoints - 1
88.             TempChain(ShapeCount, k).x = (1 / 2) * (PointChain(ShapeCount, k - 1).x + PointChain(ShapeCount, k + 1).x)
89.             TempChain(ShapeCount, k).y = (1 / 2) * (PointChain(ShapeCount, k - 1).y + PointChain(ShapeCount, k + 1).y)
90.         FOR k = 2 TO numpoints - 1
91.             PointChain(ShapeCount, k).x = TempChain(ShapeCount, k).x
92.             PointChain(ShapeCount, k).y = TempChain(ShapeCount, k).y
93.
94.     Shape(ShapeCount).Elements = numpoints
95.     Shape(ShapeCount).Shade = _RGB(100 + INT(RND * 155), 100 + INT(RND * 155), 100 + INT(RND * 155))
96.     SelectedShape = ShapeCount
97.
98. SUB cpset (x1, y1, col AS _UNSIGNED LONG)
99.     PSET (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col
100.
101. SUB cprintstring (y, a AS STRING)
102.     _PRINTSTRING (_WIDTH / 2 - (LEN(a) * 8) / 2, -y + _HEIGHT / 2), a
103.
104. SUB lineSmooth (x0, y0, x1, y1, c AS _UNSIGNED LONG)
105.     'translated from
106.     'https://en.wikipedia.org/w/index.php?title=Xiaolin_Wu%27s_line_algorithm&oldid=852445548
107.
108.     DIM plX AS INTEGER, plY AS INTEGER, plI
109.
110.     DIM steep AS _BYTE
111.     steep = ABS(y1 - y0) > ABS(x1 - x0)
112.
113.     IF steep THEN
114.         SWAP x0, y0
115.         SWAP x1, y1
116.
117.     IF x0 > x1 THEN
118.         SWAP x0, x1
119.         SWAP y0, y1
120.
121.     DIM dx, dy, gradient
122.     dx = x1 - x0
123.     dy = y1 - y0
124.     gradient = dy / dx
125.
126.     IF dx = 0 THEN
127.         gradient = 1
128.
129.     'handle first endpoint
130.     DIM xend, yend, xgap, xpxl1, ypxl1
131.     xend = _ROUND(x0)
132.     yend = y0 + gradient * (xend - x0)
133.     xgap = (1 - ((x0 + .5) - INT(x0 + .5)))
134.     xpxl1 = xend 'this will be used in the main loop
135.     ypxl1 = INT(yend)
136.     IF steep THEN
137.         plX = ypxl1
138.         plY = xpxl1
139.         plI = (1 - (yend - INT(yend))) * xgap
140.         GOSUB plot
141.
142.         plX = ypxl1 + 1
143.         plY = xpxl1
144.         plI = (yend - INT(yend)) * xgap
145.         GOSUB plot
146.         plX = xpxl1
147.         plY = ypxl1
148.         plI = (1 - (yend - INT(yend))) * xgap
149.         GOSUB plot
150.
151.         plX = xpxl1
152.         plY = ypxl1 + 1
153.         plI = (yend - INT(yend)) * xgap
154.         GOSUB plot
155.
156.     DIM intery
157.     intery = yend + gradient 'first y-intersection for the main loop
158.
159.     'handle second endpoint
160.     DIM xpxl2, ypxl2
161.     xend = _ROUND(x1)
162.     yend = y1 + gradient * (xend - x1)
163.     xgap = ((x1 + .5) - INT(x1 + .5))
164.     xpxl2 = xend 'this will be used in the main loop
165.     ypxl2 = INT(yend)
166.     IF steep THEN
167.         plX = ypxl2
168.         plY = xpxl2
169.         plI = (1 - (yend - INT(yend))) * xgap
170.         GOSUB plot
171.
172.         plX = ypxl2 + 1
173.         plY = xpxl2
174.         plI = (yend - INT(yend)) * xgap
175.         GOSUB plot
176.         plX = xpxl2
177.         plY = ypxl2
178.         plI = (1 - (yend - INT(yend))) * xgap
179.         GOSUB plot
180.
181.         plX = xpxl2
182.         plY = ypxl2 + 1
183.         plI = (yend - INT(yend)) * xgap
184.         GOSUB plot
185.
186.     'main loop
187.     DIM x
188.     IF steep THEN
189.         FOR x = xpxl1 + 1 TO xpxl2 - 1
190.             plX = INT(intery)
191.             plY = x
192.             plI = (1 - (intery - INT(intery)))
193.             GOSUB plot
194.
195.             plX = INT(intery) + 1
196.             plY = x
197.             plI = (intery - INT(intery))
198.             GOSUB plot
199.
200.             intery = intery + gradient
201.         FOR x = xpxl1 + 1 TO xpxl2 - 1
202.             plX = x
203.             plY = INT(intery)
204.             plI = (1 - (intery - INT(intery)))
205.             GOSUB plot
206.
207.             plX = x
208.             plY = INT(intery) + 1
209.             plI = (intery - INT(intery))
210.             GOSUB plot
211.
212.             intery = intery + gradient
213.
214.
215.     plot:
216.     ' Change to regular PSET for standard coordinate orientation.
217.     CALL cpset(plX, plY, _RGB32(_RED32(c), _GREEN32(c), _BLUE32(c), plI * 255))
218.

« Last Edit: March 21, 2020, 11:35:01 PM by The Librarian »