Tanoda
CableCurve.cs
Go to the documentation of this file.
1
4
5using System;
6using System.Collections.Generic;
7
9{
10 [System.Serializable]
11 public class CableCurve
12 {
13 [SerializeField]
14 Vector2 m_start;
15 [SerializeField]
16 Vector2 m_end;
17 [SerializeField]
18 float m_slack;
19 [SerializeField]
20 int m_steps;
21 [SerializeField]
22 bool m_regen;
23
24 static Vector2[] emptyCurve = new Vector2[] { new Vector2(0.0f, 0.0f), new Vector2(0.0f, 0.0f) };
25 [SerializeField]
26 Vector2[] points;
27
28 public bool regenPoints
29 {
30 get { return m_regen; }
31 set
32 {
33 m_regen = value;
34 }
35 }
36
37 public Vector2 start
38 {
39 get { return m_start; }
40 set
41 {
42 if (value != m_start)
43 m_regen = true;
44 m_start = value;
45 }
46 }
47
48 public Vector2 end
49 {
50 get { return m_end; }
51 set
52 {
53 if (value != m_end)
54 m_regen = true;
55 m_end = value;
56 }
57 }
58 public float slack
59 {
60 get { return m_slack; }
61 set
62 {
63 if (value != m_slack)
64 m_regen = true;
65 m_slack = Mathf.Max(0.0f, value);
66 }
67 }
68 public int steps
69 {
70 get { return m_steps; }
71 set
72 {
73 if (value != m_steps)
74 m_regen = true;
75 m_steps = Mathf.Max(2, value);
76 }
77 }
78
79 public Vector2 midPoint
80 {
81 get
82 {
83 Vector2 mid = Vector2.zero;
84 if (m_steps == 2)
85 {
86 return (points[0] + points[1]) * 0.5f;
87 }
88 else if (m_steps > 2)
89 {
90 int m = m_steps / 2;
91 if ((m_steps % 2) == 0)
92 {
93 mid = (points[m] + points[m + 1]) * 0.5f;
94 }
95 else
96 {
97 mid = points[m];
98 }
99 }
100 return mid;
101 }
102 }
103
104 public CableCurve()
105 {
106 points = emptyCurve;
107 m_start = Vector2.up;
108 m_end = Vector2.up + Vector2.right;
109 m_slack = 0.5f;
110 m_steps = 20;
111 m_regen = true;
112 }
113
114 public CableCurve(Vector2[] inputPoints)
115 {
116 points = inputPoints;
117 m_start = inputPoints[0];
118 m_end = inputPoints[1];
119 m_slack = 0.5f;
120 m_steps = 20;
121 m_regen = true;
122 }
123
124 public CableCurve(List<Vector2> inputPoints)
125 {
126 points = inputPoints.ToArray();
127 m_start = inputPoints[0];
128 m_end = inputPoints[1];
129 m_slack = 0.5f;
130 m_steps = 20;
131 m_regen = true;
132 }
133
135 {
136 points = v.Points();
137 m_start = v.start;
138 m_end = v.end;
139 m_slack = v.slack;
140 m_steps = v.steps;
141 m_regen = v.regenPoints;
142 }
143
144 public Vector2[] Points()
145 {
146 if (!m_regen)
147 return points;
148
149 if (m_steps < 2)
150 return emptyCurve;
151
152 float lineDist = Vector2.Distance(m_end, m_start);
153 float lineDistH = Vector2.Distance(new Vector2(m_end.x, m_start.y), m_start);
154 float l = lineDist + Mathf.Max(0.0001f, m_slack);
155 float r = 0.0f;
156 float s = m_start.y;
157 float u = lineDistH;
158 float v = end.y;
159
160 if ((u - r) == 0.0f)
161 return emptyCurve;
162
163 float ztarget = Mathf.Sqrt(Mathf.Pow(l, 2.0f) - Mathf.Pow(v - s, 2.0f)) / (u - r);
164
165 int loops = 30;
166 int iterationCount = 0;
167 int maxIterations = loops * 10; // For safety.
168 bool found = false;
169
170 float z = 0.0f;
171 float ztest = 0.0f;
172 float zstep = 100.0f;
173 float ztesttarget = 0.0f;
174 for (int i = 0; i < loops; i++)
175 {
176 for (int j = 0; j < 10; j++)
177 {
178 iterationCount++;
179 ztest = z + zstep;
180 ztesttarget = (float)Math.Sinh(ztest) / ztest;
181
182 if (float.IsInfinity(ztesttarget))
183 continue;
184
185 if (ztesttarget == ztarget)
186 {
187 found = true;
188 z = ztest;
189 break;
190 }
191 else if (ztesttarget > ztarget)
192 {
193 break;
194 }
195 else
196 {
197 z = ztest;
198 }
199
200 if (iterationCount > maxIterations)
201 {
202 found = true;
203 break;
204 }
205 }
206
207 if (found)
208 break;
209
210 zstep *= 0.1f;
211 }
212
213 float a = (u - r) / 2.0f / z;
214 float p = (r + u - a * Mathf.Log((l + v - s) / (l - v + s))) / 2.0f;
215 float q = (v + s - l * (float)Math.Cosh(z) / (float)Math.Sinh(z)) / 2.0f;
216
217 points = new Vector2[m_steps];
218 float stepsf = m_steps - 1;
219 float stepf;
220 for (int i = 0; i < m_steps; i++)
221 {
222 stepf = i / stepsf;
223 Vector2 pos = Vector2.zero;
224 pos.x = Mathf.Lerp(start.x, end.x, stepf);
225 pos.y = a * (float)Math.Cosh(((stepf * lineDistH) - p) / a) + q;
226 points[i] = pos;
227 }
228
229 m_regen = false;
230 return points;
231 }
232 }
233}
Es.InkPainter.Math Math
Definition: PaintTest.cs:7
CableCurve(List< Vector2 > inputPoints)
Definition: CableCurve.cs:124
CableCurve(Vector2[] inputPoints)
Definition: CableCurve.cs:114
Credit Erdener Gonenc - @PixelEnvision.