1 /**
2  * libdmtx - Data Matrix Encoding/Decoding Library
3  * Copyright 2008, 2009 Mike Laughton. All rights reserved.
4  * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved.
5  *
6  * See LICENSE file in the main project directory for full
7  * terms of use and distribution.
8  *
9  * Contact:
10  * Vadim A. Misbakh-Soloviov <dmtx@mva.name>
11  * Mike Laughton <mike@dragonflylogic.com>
12  *
13  * \file dmtxvector2.c
14  * \brief 2D Vector math
15  */
16 
17 /**
18  *
19  *
20  */
21 extern DmtxVector2 *
dmtxVector2AddTo(DmtxVector2 * v1,const DmtxVector2 * v2)22 dmtxVector2AddTo(DmtxVector2 *v1, const DmtxVector2 *v2)
23 {
24    v1->X += v2->X;
25    v1->Y += v2->Y;
26 
27    return v1;
28 }
29 
30 /**
31  *
32  *
33  */
34 extern DmtxVector2 *
dmtxVector2Add(DmtxVector2 * vOut,const DmtxVector2 * v1,const DmtxVector2 * v2)35 dmtxVector2Add(DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2)
36 {
37    *vOut = *v1;
38 
39    return dmtxVector2AddTo(vOut, v2);
40 }
41 
42 /**
43  *
44  *
45  */
46 extern DmtxVector2 *
dmtxVector2SubFrom(DmtxVector2 * v1,const DmtxVector2 * v2)47 dmtxVector2SubFrom(DmtxVector2 *v1, const DmtxVector2 *v2)
48 {
49    v1->X -= v2->X;
50    v1->Y -= v2->Y;
51 
52    return v1;
53 }
54 
55 /**
56  *
57  *
58  */
59 extern DmtxVector2 *
dmtxVector2Sub(DmtxVector2 * vOut,const DmtxVector2 * v1,const DmtxVector2 * v2)60 dmtxVector2Sub(DmtxVector2 *vOut, const DmtxVector2 *v1, const DmtxVector2 *v2)
61 {
62    *vOut = *v1;
63 
64    return dmtxVector2SubFrom(vOut, v2);
65 }
66 
67 /**
68  *
69  *
70  */
71 extern DmtxVector2 *
dmtxVector2ScaleBy(DmtxVector2 * v,double s)72 dmtxVector2ScaleBy(DmtxVector2 *v, double s)
73 {
74    v->X *= s;
75    v->Y *= s;
76 
77    return v;
78 }
79 
80 /**
81  *
82  *
83  */
84 extern DmtxVector2 *
dmtxVector2Scale(DmtxVector2 * vOut,const DmtxVector2 * v,double s)85 dmtxVector2Scale(DmtxVector2 *vOut, const DmtxVector2 *v, double s)
86 {
87    *vOut = *v;
88 
89    return dmtxVector2ScaleBy(vOut, s);
90 }
91 
92 /**
93  *
94  *
95  */
96 extern double
dmtxVector2Cross(const DmtxVector2 * v1,const DmtxVector2 * v2)97 dmtxVector2Cross(const DmtxVector2 *v1, const DmtxVector2 *v2)
98 {
99    return (v1->X * v2->Y) - (v1->Y * v2->X);
100 }
101 
102 /**
103  *
104  *
105  */
106 extern double
dmtxVector2Norm(DmtxVector2 * v)107 dmtxVector2Norm(DmtxVector2 *v)
108 {
109    double mag;
110 
111    mag = dmtxVector2Mag(v);
112 
113    if(mag <= DmtxAlmostZero)
114       return -1.0; /* XXX this doesn't look clean */
115 
116    dmtxVector2ScaleBy(v, 1/mag);
117 
118    return mag;
119 }
120 
121 /**
122  *
123  *
124  */
125 extern double
dmtxVector2Dot(const DmtxVector2 * v1,const DmtxVector2 * v2)126 dmtxVector2Dot(const DmtxVector2 *v1, const DmtxVector2 *v2)
127 {
128    return (v1->X * v2->X) + (v1->Y * v2->Y);
129 }
130 
131 /**
132  *
133  *
134  */
135 extern double
dmtxVector2Mag(const DmtxVector2 * v)136 dmtxVector2Mag(const DmtxVector2 *v)
137 {
138    return sqrt(v->X * v->X + v->Y * v->Y);
139 }
140 
141 /**
142  *
143  *
144  */
145 extern double
dmtxDistanceFromRay2(const DmtxRay2 * r,const DmtxVector2 * q)146 dmtxDistanceFromRay2(const DmtxRay2 *r, const DmtxVector2 *q)
147 {
148    DmtxVector2 vSubTmp;
149 
150    /* Assumes that v is a unit vector */
151    assert(fabs(1.0 - dmtxVector2Mag(&(r->v))) <= DmtxAlmostZero);
152 
153    return dmtxVector2Cross(&(r->v), dmtxVector2Sub(&vSubTmp, q, &(r->p)));
154 }
155 
156 /**
157  *
158  *
159  */
160 extern double
dmtxDistanceAlongRay2(const DmtxRay2 * r,const DmtxVector2 * q)161 dmtxDistanceAlongRay2(const DmtxRay2 *r, const DmtxVector2 *q)
162 {
163    DmtxVector2 vSubTmp;
164 
165 #ifdef DEBUG
166    /* Assumes that v is a unit vector */
167    if(fabs(1.0 - dmtxVector2Mag(&(r->v))) > DmtxAlmostZero) {
168       ; /* XXX big error goes here */
169    }
170 #endif
171 
172    return dmtxVector2Dot(dmtxVector2Sub(&vSubTmp, q, &(r->p)), &(r->v));
173 }
174 
175 /**
176  *
177  *
178  */
179 extern DmtxPassFail
dmtxRay2Intersect(DmtxVector2 * point,const DmtxRay2 * p0,const DmtxRay2 * p1)180 dmtxRay2Intersect(DmtxVector2 *point, const DmtxRay2 *p0, const DmtxRay2 *p1)
181 {
182    double numer, denom;
183    DmtxVector2 w;
184 
185    denom = dmtxVector2Cross(&(p1->v), &(p0->v));
186    if(fabs(denom) <= DmtxAlmostZero)
187       return DmtxFail;
188 
189    dmtxVector2Sub(&w, &(p1->p), &(p0->p));
190    numer = dmtxVector2Cross(&(p1->v), &w);
191 
192    return dmtxPointAlongRay2(point, p0, numer/denom);
193 }
194 
195 /**
196  *
197  *
198  */
199 extern DmtxPassFail
dmtxPointAlongRay2(DmtxVector2 * point,const DmtxRay2 * r,double t)200 dmtxPointAlongRay2(DmtxVector2 *point, const DmtxRay2 *r, double t)
201 {
202    DmtxVector2 vTmp;
203 
204    /* Ray should always have unit length of 1 */
205    assert(fabs(1.0 - dmtxVector2Mag(&(r->v))) <= DmtxAlmostZero);
206 
207    dmtxVector2Scale(&vTmp, &(r->v), t);
208    dmtxVector2Add(point, &(r->p), &vTmp);
209 
210    return DmtxPass;
211 }
212