1 /*
2 *	Copyright (C) 2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
3 *
4 *	This program is free software: you can redistribute it and/or modify
5 *	it under the terms of the GNU Lesser General Public License as published
6 *	by the Free Software Foundation, either version 3 of the License, or
7 *	(at your option) any later version.
8 *
9 *	This program is distributed in the hope that it will be useful,
10 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 *	GNU Lesser General Public License for more details.
13 *
14 *	You should have received a copy of the GNU Lesser General Public License
15 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "ParameterCoord.h"
19 #include "tinyxml.h"
20 #include <sstream>
21 
TransformCoordSystem(const double * inCoord,double * out,CoordinateSystem CS_In,CoordinateSystem CS_out)22 double* TransformCoordSystem(const double* inCoord, double* out, CoordinateSystem CS_In, CoordinateSystem CS_out)
23 {
24 	double in[3] = {inCoord[0],inCoord[1],inCoord[2]};
25 	switch (CS_In)
26 	{
27 	case CARTESIAN: //input coords are cartesian
28 		switch (CS_out)
29 		{
30 		default: //unknown transform --> just copy
31 		case CARTESIAN: // transform cartesian --> cartesian
32 			for (int n=0;n<3;++n)
33 				out[n] = in[n];  //just copy
34 			break;
35 		case CYLINDRICAL: // transform cartesian --> cylindrical
36 			out[0] = sqrt(in[0]*in[0]+in[1]*in[1]); // r = sqrt(x²+y²)
37 			out[1] = atan2(in[1],in[0]); //alpha = atan2(y,x)
38 			out[2] = in[2]; //z==z
39 			break;
40 		}
41 		break;
42 	case CYLINDRICAL: //input coords are cylindrical
43 		switch (CS_out)
44 		{
45 		case CARTESIAN: // transform cylindrical --> cartesian
46 			out[0] = in[0] * cos(in[1]); // x = r * cos(alpha)
47 			out[1] = in[0] * sin(in[1]); // y = r * sin(alpha)
48 			out[2] = in[2]; // z = z
49 			break;
50 		default: //unknown transform --> just copy
51 		case CYLINDRICAL: // transform cylindrical --> cylindrical
52 			for (int n=0;n<3;++n)
53 				out[n] = in[n];  //just copy
54 			break;
55 		}
56 		break;
57 	default: //unknown transform --> just copy
58 		for (int n=0;n<3;++n)
59 			out[n] = in[n];  //just copy
60 	}
61 	return out;
62 }
63 
ParameterCoord()64 ParameterCoord::ParameterCoord()
65 {
66 	m_CoordSystem = UNDEFINED_CS;
67 	for (int n=0;n<3;++n)
68 		m_Coords[n] = new ParameterScalar();
69 	Update();
70 }
71 
ParameterCoord(ParameterSet * ParaSet)72 ParameterCoord::ParameterCoord(ParameterSet* ParaSet)
73 {
74 	m_CoordSystem = UNDEFINED_CS;
75 	for (int n=0;n<3;++n)
76 		m_Coords[n] = new ParameterScalar(ParaSet,0);
77 	Update();
78 }
79 
ParameterCoord(CoordinateSystem cs)80 ParameterCoord::ParameterCoord(CoordinateSystem cs)
81 {
82 	m_CoordSystem = cs;
83 	for (int n=0;n<3;++n)
84 		m_Coords[n] = new ParameterScalar();
85 	Update();
86 }
87 
ParameterCoord(ParameterSet * ParaSet,const double value[3])88 ParameterCoord::ParameterCoord(ParameterSet* ParaSet, const double value[3])
89 {
90 	m_CoordSystem = UNDEFINED_CS;
91 	for (int n=0;n<3;++n)
92 		m_Coords[n] = new ParameterScalar(ParaSet, value[n]);
93 	Update();
94 }
95 
ParameterCoord(ParameterSet * ParaSet,const std::string value[3])96 ParameterCoord::ParameterCoord(ParameterSet* ParaSet, const std::string value[3])
97 {
98 	m_CoordSystem = UNDEFINED_CS;
99 	for (int n=0;n<3;++n)
100 		m_Coords[n] = new ParameterScalar(ParaSet, value[n]);
101 	Update();
102 }
103 
ParameterCoord(ParameterCoord * pc)104 ParameterCoord::ParameterCoord(ParameterCoord* pc)
105 {
106 	m_CoordSystem = UNDEFINED_CS;
107 	for (int n=0;n<3;++n)
108 		m_Coords[n]=NULL;
109 	Copy(pc);
110 }
111 
~ParameterCoord()112 ParameterCoord::~ParameterCoord()
113 {
114 	for (int n=0;n<3;++n)
115 	{
116 		delete m_Coords[n];
117 		m_Coords[n]=NULL;
118 	}
119 }
120 
SetParameterSet(ParameterSet * paraSet)121 void ParameterCoord::SetParameterSet(ParameterSet *paraSet)
122 {
123 	for (int n=0;n<3;++n)
124 		m_Coords[n]->SetParameterSet(paraSet);
125 	Update();
126 }
127 
SetCoordinateSystem(CoordinateSystem cs,CoordinateSystem fallBack_cs)128 void ParameterCoord::SetCoordinateSystem(CoordinateSystem cs, CoordinateSystem fallBack_cs)
129 {
130 	if (cs!=UNDEFINED_CS)
131 		return SetCoordinateSystem(cs);
132 	return SetCoordinateSystem(fallBack_cs);
133 }
134 
SetValue(int ny,std::string value)135 int ParameterCoord::SetValue(int ny, std::string value)
136 {
137 	if ((ny<0) || (ny>2))
138 		return -1;
139 	int EC = m_Coords[ny]->SetValue(value);
140 	Update();
141 	return EC;
142 }
143 
SetValue(int ny,double value)144 void ParameterCoord::SetValue(int ny, double value)
145 {
146 	if ((ny<0) || (ny>2))
147 		return;
148 	m_Coords[ny]->SetValue(value);
149 	Update();
150 }
151 
GetValue(int ny)152 double ParameterCoord::GetValue(int ny)
153 {
154 	if ((ny<0) || (ny>2))
155 		return nan("");
156 	return m_Coords[ny]->GetValue();
157 }
158 
GetValueString(int ny) const159 const std::string ParameterCoord::GetValueString(int ny) const
160 {
161 	if ((ny<0) || (ny>2))
162 		return "nan";
163 	return m_Coords[ny]->GetValueString();
164 }
165 
GetCoordValue(int ny,CoordinateSystem cs)166 double ParameterCoord::GetCoordValue(int ny, CoordinateSystem cs)
167 {
168 	if ((ny<0) || (ny>2))
169 		return nan("");
170 	return GetCoords(cs)[ny];
171 }
172 
GetCoordPS(int ny)173 ParameterScalar* ParameterCoord::GetCoordPS(int ny)
174 {
175 	if ((ny>=0) && (ny<3))
176 		return m_Coords[ny];
177 	return 0;
178 }
179 
GetNativeCoords() const180 const double* ParameterCoord::GetNativeCoords() const
181 {
182 	switch (m_CoordSystem)
183 	{
184 	default:
185 	case CARTESIAN:
186 		return GetCartesianCoords();
187 	case CYLINDRICAL:
188 		return GetCylindricalCoords();
189 	}
190 	return NULL; //this should not happen...
191 }
192 
GetCoords(CoordinateSystem cs) const193 const double* ParameterCoord::GetCoords(CoordinateSystem cs) const
194 {
195 	switch (cs)
196 	{
197 	case CARTESIAN:
198 		return GetCartesianCoords();
199 	case CYLINDRICAL:
200 		return GetCylindricalCoords();
201 	default:
202 		return GetNativeCoords();
203 	}
204 }
205 
Evaluate(std::string * ErrStr)206 bool ParameterCoord::Evaluate(std::string *ErrStr)
207 {
208 	int EC=0;
209 	bool bOK=true;
210 	for (int i=0;i<3;++i)
211 	{
212 		EC=m_Coords[i]->Evaluate();
213 		if (EC!=ParameterScalar::PS_NO_ERROR) bOK=false;
214 		if ((EC!=ParameterScalar::PS_NO_ERROR)  && (ErrStr!=NULL))
215 		{
216 			std::stringstream stream;
217 			stream << std::endl << "Error in ParameterCoord (component: " << i << "): ";
218 			ErrStr->append(stream.str());
219 			PSErrorCode2Msg(EC,ErrStr);
220 		}
221 	}
222 	return bOK;
223 }
224 
Copy(ParameterCoord * pc)225 void ParameterCoord::Copy(ParameterCoord* pc)
226 {
227 	m_CoordSystem = pc->m_CoordSystem;
228 	for (int n=0;n<3;++n)
229 	{
230 		delete m_Coords[n];
231 		m_Coords[n] = new ParameterScalar(pc->m_Coords[n]);
232 	}
233 	Update();
234 }
235 
Update()236 void ParameterCoord::Update()
237 {
238 	double coords[3] = {m_Coords[0]->GetValue(),m_Coords[1]->GetValue(),m_Coords[2]->GetValue()};
239 	TransformCoordSystem(coords, m_CartesianCoords, m_CoordSystem, CARTESIAN);
240 	TransformCoordSystem(coords, m_CylindricalCoords, m_CoordSystem, CYLINDRICAL);
241 }
242 
Write2XML(TiXmlElement * elem,bool parameterised)243 bool ParameterCoord::Write2XML(TiXmlElement *elem, bool parameterised)
244 {
245 	if (elem==NULL)
246 		return false;
247 	WriteTerm(*m_Coords[0],*elem,"X",parameterised);
248 	WriteTerm(*m_Coords[1],*elem,"Y",parameterised);
249 	WriteTerm(*m_Coords[2],*elem,"Z",parameterised);
250 	return true;
251 }
252 
ReadFromXML(TiXmlElement * elem)253 bool ParameterCoord::ReadFromXML(TiXmlElement *elem)
254 {
255 	if (elem==NULL)
256 		return false;
257 	if (ReadTerm(*m_Coords[0],*elem,"X")==false) return false;
258 	if (ReadTerm(*m_Coords[1],*elem,"Y")==false) return false;
259 	if (ReadTerm(*m_Coords[2],*elem,"Z")==false) return false;
260 	return true;
261 }
262