 Author Topic: Curve Smoother by STxAxTIC  (Read 1736 times) The Librarian

• Moderator Curve Smoother by STxAxTIC
« on: March 17, 2018, 01:08:19 AM »
Curve Smoother

Author: STxAxTIC
Source: Submission
Version: 2014
Tags: [drawing]

Description:
This program demonstrates (i) linear interpolation, and (ii) a relaxation technique to "smooth out" a hand-drawn curve. Several controls over the resolution and "smooth factor" can be tweaked at the top of the code.

Source code:
Code: QB64 [Select]
1. '
2. ' Primary degrees of freedom:
3. '
4. rawresolution = 10 ' Raw curve resolution.
5. targetpoints = 400 ' Number of points per curve.
6. smoothiterations = 40 ' Magnitude of `smooth' effect.
7.
8. ' ********** ********** ********** ********** **********
9.
10. screenwidth = 640
11. screenheight = 480
12. centerx = screenwidth / 2
13. centery = screenheight / 2
14.
15. start:
16.
17. REDIM pointchainx(999, targetpoints)
18. REDIM pointchainy(999, targetpoints)
19. REDIM tempchainx(999, targetpoints)
20. REDIM tempchainy(999, targetpoints)
21.
22. curvenum = 0
23. exitflag = 0
24. xold = 999999
25. yold = 999999
26.
27. GOSUB refresh
28.
29.     curvenum = curvenum + 1
30.     numpoints = 0
31.
32.     '
33.     ' Gather raw data for one curve at a time.
34.     ' Click+drag mouse button 1 to trace out a curve.
35.     '
36.             x = _MOUSEX
37.             y = _MOUSEY
38.             IF (x > 0) AND (x < screenwidth) AND (y > 0) AND (y < screenheight) THEN
39.                     GOSUB unconvert
40.                     delta = SQR((x - xold) ^ 2 + (y - yold) ^ 2)
41.                     '
42.                     ' Collect data only if the new point is sufficiently far away from the previous point.
43.                     '
44.                     IF (delta > rawresolution) AND (numpoints < targetpoints - 1) THEN
45.                         numpoints = numpoints + 1
46.                         pointchainx(curvenum, numpoints) = x
47.                         pointchainy(curvenum, numpoints) = y
48.                         xold = x: yold = y
49.                         GOSUB convert
50.                         PSET (x, y), 14
51.
52.             CASE " "
53.                 GOTO start
54.             CASE CHR\$(27)
55.                 exitflag = 1
56.                 GOTO quitsequence
57.
58.     LOOP UNTIL NOT _MOUSEBUTTON(1) AND numpoints > 1
59.
60.     '
61.     ' If the curve contains less than the minimum numer of points, use interpolation to fill in the gaps.
62.     '
63.         '
64.         ' Determine the pair of neighboring points that have the greatest separation of all pairs.
65.         '
66.         rad2max = -1
67.         kmax = -1
68.         FOR k = 1 TO numpoints - 1
69.             xfac = pointchainx(curvenum, k) - pointchainx(curvenum, k + 1)
70.             yfac = pointchainy(curvenum, k) - pointchainy(curvenum, k + 1)
71.             rad2 = xfac ^ 2 + yfac ^ 2
73.                 kmax = k
75.
76.         '
77.         ' Starting next to kmax, create a `gap' by shifting all other points by one index.
78.         '
79.         FOR j = numpoints TO kmax + 1 STEP -1
80.             pointchainx(curvenum, j + 1) = pointchainx(curvenum, j)
81.             pointchainy(curvenum, j + 1) = pointchainy(curvenum, j)
82.
83.         '
84.         ' Fill the gap with a new point whose position is determined by the average of its neighbors.
85.         '
86.         pointchainx(curvenum, kmax + 1) = (1 / 2) * (pointchainx(curvenum, kmax) + pointchainx(curvenum, kmax + 2))
87.         pointchainy(curvenum, kmax + 1) = (1 / 2) * (pointchainy(curvenum, kmax) + pointchainy(curvenum, kmax + 2))
88.
89.         numpoints = numpoints + 1
90.     LOOP UNTIL (numpoints = targetpoints)
91.
92.     GOSUB refresh
93.
94.     '
95.     ' At this stage, the curve still has all of its sharp edges. Use a `relaxation method' to smooth.
96.     ' The new position of a point is equal to the average position of its neighboring points.
97.     '
98.     FOR j = 1 TO smoothiterations
99.         FOR k = 2 TO numpoints - 1
100.             tempchainx(curvenum, k) = (1 / 2) * (pointchainx(curvenum, k - 1) + pointchainx(curvenum, k + 1))
101.             tempchainy(curvenum, k) = (1 / 2) * (pointchainy(curvenum, k - 1) + pointchainy(curvenum, k + 1))
102.         FOR k = 2 TO numpoints - 1
103.             pointchainx(curvenum, k) = tempchainx(curvenum, k)
104.             pointchainy(curvenum, k) = tempchainy(curvenum, k)
105.
106.     GOSUB refresh
107.
108. LOOP UNTIL exitflag = 1
109.
110. quitsequence:
111.
112. refresh:
113. GOSUB printbackground
114. GOSUB drawcurves
115.
116. printbackground:
117. PRINT "                  Drag the left mouse button to draw a curve."
118. PRINT "                Single left-clicking generates straight lines."
119. PRINT "             After drawing a curve, watch it smooth after 1 second."
120.
121. ' Draw curves.
122. drawcurves:
123. FOR w = 1 TO curvenum
124.     FOR k = 1 TO targetpoints - 1
125.         x = pointchainx(w, k)
126.         y = pointchainy(w, k)
127.         GOSUB convert
128.         xa = x: ya = y
129.         x = pointchainx(w, k + 1)
130.         y = pointchainy(w, k + 1)
131.         GOSUB convert
132.         xb = x: yb = y
133.         LINE (xa, ya)-(xb, yb), 14
134.
135. ' Convert from cartesian coordinates to screen coordinates.
136. convert:
137. x0 = x: y0 = y
138. x = x0 + centerx
139. y = -y0 + centery
140.
141. ' Inverse of the above conversion.
142. unconvert:
143. x0 = x: y0 = y
144. x = x0 - centerx
145. y = -y0 + centery
146.

« Last Edit: August 08, 2018, 11:17:39 PM by odin »