TWOD.C
[目次 | 関数]
1|/**************************************************************************
2|* 1. <<< 二次元グラフィックス(代数)(TwoD) >>>
3|***************************************************************************/
4|
5|#include <math.h>
6|#ifdef USES_MXP_AUTOINC
7| #include "twod.ah" /* Auto include header, Look at mixer-... folder */
8|#else
9| #include <all.h>
10|#endif
11|
12|
13|
14|/*-------------------------------------------------------------------------*/
15|/* 2. <<< ◆二次元座標 (TwoD_XY) >>>
16|/*-------------------------------------------------------------------------*/
17|
18|
19|
20|/*************************************************************************
21|* 3. <<< [TwoD_XY_rot] 回転する >>>
22|*【引数】
23|* ・TwoD_XY* center; 回転する座標(入出力)
24|* ・TwoD_XY* center; 回転の中心座標
25|* ・double radian; 角度(左回り、ラジアン、座標系に注意)
26|*【補足】
27|*・radian は、X 軸の右向きが Y 軸(一般のグラフィック画面)の場合のものです。
28|* 左向きに Y 軸がある場合、マイナスの radian を指定します。
29|**************************************************************************/
30|void TwoD_XY_rot( TwoD_XY* m, const TwoD_XY* center, double radian )
31|{
32| double x;
33|
34| ERRORS_FUNC_START( TwoD_XY_rot );
35|
36| m->x -= center->x; m->y -= center->y;
37|
38| x = m->x;
39| m->x = x * cos(radian) - m->y * sin(radian);
40| m->y = x * sin(radian) + m->y * cos(radian);
41|
42| m->x += center->x; m->y += center->y;
43|
44| ERRORS_FUNC_END( TwoD_XY_rot );
45|}
46|
47|
48|#ifdef USES_THREED
49|/*************************************************************************
50|* 4. <<< [TwoD_XY_initBy3D] 三次元座標から二次元座標を初期化する >>>
51|*【補足】
52|*・p の座標系は、ThreeD_TwoD_initByP3 関数で f を初期化したときのものと
53|* 同じ座標系にしてください。
54|**************************************************************************/
55|void TwoD_XY_initBy3D( TwoD_XY* m, ThreeD_TwoD* f, ThreeD_XYZ* p )
56|{
57| ERRORS_FUNC_START( TwoD_XY_initBy3D );
58|
59| m->x = ThreeD_Vect_getDirLen( (ThreeD_Vect*)p, &f->x_coord );
60| m->y = ThreeD_Vect_getDirLen( (ThreeD_Vect*)p, &f->y_coord );
61|
62| ERRORS_FUNC_END( TwoD_XY_initBy3D );
63|}
64|#endif /* USES_THREED */
65|
66|
67|
68|/*************************************************************************
69|* 5. <<< [TwoD_XY_getCrossLineH] 水平線と線分の交点座標を格納する >>>
70|*【引数】
71|* ・double y; 水平線の Y 座標
72|* ・TwoD_XY* p1, p2; 線分の両端の点
73|* ・TwoD_XY* out; 交点座標
74|* ・int 返り値; 0=正常、1=線分と水平線は交わらない、
75|* 2=線分と水平線は平行
76|*【補足】
77|*・返り値が 1 の場合、out には、線分を直線とした交点座標を格納します。
78|*・返り値が 2 の場合、out には、元の値が格納されたままになります。
79|*・たとえば、次の図のように、指定した点を含む水平線(X 軸平行線)を考える際に、
80|* 使用します。
81|*
82|*・水平線が線分に接する場合、線分の上端(Y小)なら交わる、線分の下端(Y大)なら
83|* 交わらないと判定します。
84|**************************************************************************/
85|int TwoD_XY_getCrossLineH( double y, TwoD_XY* p1, TwoD_XY* p2,
86| TwoD_XY* out )
87|{
88| ERRORS_FUNC_START( TwoD_XY_getCrossLineH );
89|
90| /* p1 の Y 座標が p2 の Y 座標より小さくする */
91| if ( p1->y > p2->y ) {
92| TwoD_XY* s; s = p1; p1 = p2; p2 = s;
93| }
94|
95| /* 交点座標を格納する */
96| if ( p1->y == p2->y ) return 2;
97| out->x = (p1->x * (p2->y - y) + p2->x * (y - p1->y)) / (p2->y - p1->y);
98| out->y = y;
99|
100| /* 線分と交わっているか判定する */
101| ERRORS_FUNC_END( TwoD_XY_getCrossLineH );
102|
103| return ( p1->y <= y && y < p2->y ) ? 0 : 1;
104|}
105|
106|
107|
108|/*************************************************************************
109|* 6. <<< [TwoD_XY_isInPoly()] 点がポリゴンの内部にあるかどうか判定する >>>
110|*【補足】
111|*・次の図のように、指定した点を含む水平線(X 軸平行線)を考えます。
112|*
113|**************************************************************************/
114|bool TwoD_XY_isInPoly( TwoD_XY* p, TwoD_Poly* poly )
115|{
116| int i,j;
117| int count = 0;
118| TwoD_XY cross;
119|
120| ERRORS_FUNC_START( TwoD_XY_isInPoly );
121|
122| /* 指定した点を含む水平線(X 軸平行線)とポリゴン辺との交点を考え、*/
123| /* X 座標が、指定した点より小さい交点の数を数える */
124| for ( i = 0; i < poly->n; i++ ) {
125| j = ( i + 1 ) % poly->n;
126| if ( TwoD_XY_getCrossLineH( p->y, &poly->p_array[i], &poly->p_array[j],
127| &cross ) == 0 ) { /*★*/
128| if ( cross.x < p->x ) {
129| count ++;
130| }
131| }
132| }
133|
134| ERRORS_FUNC_END( TwoD_XY_isInPoly );
135|
136| return count % 2;
137|}
138|
139|
140|
141|/*************************************************************************
142|* 7. <<< [TwoD_XY_print] 属性を表示する >>>
143|**************************************************************************/
144|#ifndef ERRORS_CUT_DEBUG_TOOL
145|void TwoD_XY_print( TwoD_XY* m )
146|{
147| Errors_printf( "TwoD_XY:(%lf, %lf)", m->x, m->y );
148|}
149|#endif
150|
151|
152|
153|/*-------------------------------------------------------------------------*/
154|/* 8. <<< ◆ポリゴン (TwoD_Poly) >>> */
155|/*-------------------------------------------------------------------------*/
156|
157|
158|
159|/*************************************************************************
160|* 9. <<< [TwoD_Poly_init()] 初期化する >>>
161|**************************************************************************/
162|void TwoD_Poly_init( TwoD_Poly* m, TwoD_XY* p_array, int n, int color )
163|{
164| ERRORS_FUNC_START( TwoD_Poly_init );
165|
166| m->p_array = p_array;
167| m->n = n;
168| m->color = color;
169|
170| ERRORS_FUNC_END( TwoD_Poly_init );
171|}
172|
173|
174|
175|/*************************************************************************
176|* 10. <<< [TwoD_Poly_getConvexType] 凸型かどうか、左回りかどうか >>>
177|*【引数】
178|* ・int 返り値; 以下の定数のうちどれか(向きと座標系に注意→補足)
179|* TwoD_LeftConvex, TwoD_RightConvex, TwoD_NotConvex, TwoD_NotPoly
180|*【補足】
181|*・返り値は、X 軸の右向きが Y 軸(一般のグラフィック画面)の場合のものです。
182|* X 軸の左向きが Y 軸の場合、右回りと左回りの判定が逆になります。
183|**************************************************************************/
184|int TwoD_Poly_getConvexType( TwoD_Poly* m )
185|{
186| int ret;
187| TwoD_XY* p1;
188| TwoD_XY* p1_last2;
189| TwoD_XY* p2;
190| TwoD_XY* p3;
191| TwoD_XY v1, v2; /* ベクトル (v1=p2-p1, v2=p3-p2) */
192| int nLeft = 0; /* 左回転の回数 */
193| int nRight = 0; /* 右回転の回数 */
194| double outProd; /* 外積の値 */
195|
196| ERRORS_FUNC_START( TwoD_Poly_getConvexType );
197|
198| ASSERT( m->n >= 3 );
199|
200| #if ERRORS_DEBUG_FALSE
201| TwoD_Poly_print( m );
202| #endif
203|
204| p1 = &m->p_array[0];
205| p2 = p1 + 1;
206| p3 = p2 + 1;
207| p1_last2 = p1 + m->n - 2; /* 最後から2つ目の頂点 */
208|
209| /* nLeft, nRight を数える(最後から3つ目の頂点まで)*/
210| v1.x = p2->x - p1->x; v1.y = p2->y - p1->y;
211| for ( ; p1 < p1_last2; p1++, p2++, p3++ ) { /* 頂点数-2 */
212| v2.x = p3->x - p2->x; v2.y = p3->y - p2->y;
213|
214| outProd = TwoD_XY_getOutProd( &v1, &v2 );
215| if ( outProd < 0 ) nLeft ++;
216| else if ( outProd > 0 ) nRight ++;
217| #if ERRORS_DEBUG_FALSE
218| Errors_printf( "nLeft = %d, nRight = %d", nLeft, nRight );
219| #endif
220|
221| v1 = v2;
222| }
223|
224| /* nLeft, nRight を数える(最後から2つ目の頂点)*/
225| p3 = &m->p_array[0];
226| v2.x = p3->x - p2->x; v2.y = p3->y - p2->y;
227| outProd = TwoD_XY_getOutProd( &v1, &v2 );
228| if ( outProd < 0 ) nLeft ++;
229| else if ( outProd > 0 ) nRight ++;
230| v1 = v2;
231| #if ERRORS_DEBUG_FALSE
232| Errors_printf( "nLeft = %d, nRight = %d", nLeft, nRight );
233| #endif
234|
235| /* nLeft, nRight を数える(最後の頂点)*/
236| p1 = p3 + 1;
237| v2.x = p1->x - p3->x; v2.y = p1->y - p3->y;
238| outProd = TwoD_XY_getOutProd( &v1, &v2 );
239| if ( outProd < 0 ) nLeft ++;
240| else if ( outProd > 0 ) nRight ++;
241| #if ERRORS_DEBUG_FALSE
242| Errors_printf( "nLeft = %d, nRight = %d", nLeft, nRight );
243| #endif
244|
245| /* 判定 */
246| if ( nLeft == 0 ) {
247| if ( nRight == 0 ) ret = TwoD_NotPoly;
248| else ret = TwoD_RightConvex;
249| }
250| else {
251| if ( nRight == 0 ) ret = TwoD_LeftConvex;
252| else ret = TwoD_NotConvex;
253| }
254|
255| ERRORS_FUNC_END( TwoD_Poly_getConvexType );
256| return ret;
257|}
258|
259|
260|
261|
262|#ifdef USES_THREED
263|/*************************************************************************
264|* 11. <<< [TwoD_Poly_initByThreeD] 三次元ポリゴンから二次元ポリゴンを初期化する(1) >>>
265|*【機能】
266|*・三次元ポリゴンをスクリーン座標に変換した二次元ポリゴンとして初期化します。
267|*【引数】
268|* ・TwoD_XY* p_array; 座標を格納するメモリ領域の先頭アドレス
269|**************************************************************************/
270|void TwoD_Poly_initByThreeD( TwoD_Poly* m, TwoD_XY* p_array,
271| size_t p_array_sizeof, ThreeD_Poly* poly3, ThreeD_ViewL* view )
272|{
273| int i;
274| ThreeD_XYZ p;
275|
276| ERRORS_FUNC_START( TwoD_Poly_initByThreeD );
277|
278| ASSERT( p_array_sizeof / sizeof( TwoD_XY ) >= (unsigned int)poly3->n );
279| p_array_sizeof; /* avoid warning in release compile */
280|
281| m->p_array = p_array;
282| m->n = poly3->n;
283| m->color = poly3->color;
284|
285| for ( i = 0; i < m->n; i++ ) {
286| ThreeD_XYZ_get2D( &poly3->p_array[i], view, &p );
287| TwoD_XY_init( &m->p_array[i], p.x, p.y );
288| }
289|
290| ERRORS_FUNC_END( TwoD_Poly_initByThreeD );
291|}
292|#endif /* USES_THREED */
293|
294|
295|
296|#ifdef USES_THREED
297|/*************************************************************************
298|* 12. <<< [TwoD_Poly_initByThreeD2] 三次元ポリゴンから二次元ポリゴンを初期化する(2) >>>
299|*【機能】
300|*・三次元ポリゴン poly3 を、「ThreeD_TwoD_initByPoly などの関数で f に
301|* 定義された二次元座標」に変換して、二次元ポリゴン m を初期化します。
302|*【引数】
303|* ・TwoD_XY* p_array; m の頂点を格納するワーク領域のアドレス
304|* ・ThreeD_TwoD* f; 三次元空間内の二次元座標
305|* ・ThreeD_Poly* poly3; 三次元ポリゴン
306|**************************************************************************/
307|void TwoD_Poly_initByThreeD2( TwoD_Poly* m, TwoD_XY* p_array,
308| size_t p_array_sizeof, ThreeD_TwoD* f, ThreeD_Poly* poly3 )
309|{
310| int i;
311|
312| ERRORS_FUNC_START( TwoD_Poly_initByThreeD2 );
313|
314| ASSERT( p_array_sizeof / sizeof( TwoD_XY ) >= (unsigned int)poly3->n );
315| p_array_sizeof; /* avoid warning in release compile */
316|
317| /* 各種属性のコピー */
318| m->p_array = p_array;
319| m->n = poly3->n;
320| m->color = poly3->color;
321|
322| /* 頂点座標の変換 */
323| for ( i = 0; i < m->n; i++ ) {
324| TwoD_XY_initBy3D( &m->p_array[i], f, &poly3->p_array[i] );
325| }
326|
327| ERRORS_FUNC_END( TwoD_Poly_initByThreeD2 );
328|}
329|#endif /* USES_THREED */
330|
331|
332|
333|/*************************************************************************
334|* 13. <<< [TwoD_Poly_print] 属性をエラー表示する >>>
335|**************************************************************************/
336|#ifndef ERRORS_CUT_DEBUG_TOOL
337|void TwoD_Poly_print( TwoD_Poly* m )
338|{
339| int i;
340|
341| ERRORS_FUNC_START( TwoD_Poly_print );
342|
343| Errors_printf( "TwoD_Poly: n=%d, color=%d, ", m->n, m->color );
344| for ( i = 0; i < m->n; i++ )
345| Errors_printf( "(%lf,%lf), ", m->p_array[i].x, m->p_array[i].y );
346|
347| ERRORS_FUNC_END( TwoD_Poly_print );
348|}
349|#endif
350|
351|
352|