1 //#**************************************************************
2 //#
3 //# filename:             elementdata.cpp
4 //#
5 //# author:               Gerstmayr Johannes
6 //#
7 //# generated:						March 2010
8 //# description:          Utilities for general data structure ElementData and ElementDataContainer
9 //#
10 //# remarks:
11 //#
12 //# Copyright (c) 2003-2013 Johannes Gerstmayr, Linz Center of Mechatronics GmbH, Austrian
13 //# Center of Competence in Mechatronics GmbH, Institute of Technical Mechanics at the
14 //# Johannes Kepler Universitaet Linz, Austria. All rights reserved.
15 //#
16 //# This file is part of HotInt.
17 //# HotInt is free software: you can redistribute it and/or modify it under the terms of
18 //# the HOTINT license. See folder 'licenses' for more details.
19 //#
20 //# bug reports are welcome!!!
21 //# WWW:		www.hotint.org
22 //# email:	bug_reports@hotint.org or support@hotint.org
23 //#**************************************************************
24 
25 #include "tarray.h"
26 #include "mystring.h"
27 #include "elementdata.h"
28 
ElementData()29 ElementData::ElementData()
30 {
31 	dataname = 0;
32 	vdata = 0;
33 	vdatalen = 0;
34 	tdata = 0;
35 	locked = 0;
36 	hastooltip = 0;
37 	tooltiptext = 0;
38 	idata = 0;
39 	idata2 = 0;
40 	idata3 = 0;
41 	groupnum = 0;
42 	minval = 1;
43 	maxval = 0;
44 	oneLimit = 0;
45 	edc = 0;
46 	type = 0;
47 };
48 
ElementData(const ElementData & e)49 ElementData::ElementData(const ElementData& e)
50 {
51 	dataname = 0;
52 	vdata = 0;
53 	vdatalen = 0;
54 	tdata = 0;
55 	idata = 0;
56 	idata2 = 0;
57 	idata3 = 0;
58 	groupnum = 0;
59 	minval = 1;
60 	maxval = 0;
61 	oneLimit = 0;
62 	locked = 0;
63 	hastooltip = 0;
64 	tooltiptext = 0;
65 	edc = 0;
66 	type = 0;
67 
68 	CopyFrom(e);
69 };
70 
71 
CopyFrom(const ElementData & e)72 void ElementData::CopyFrom(const ElementData& e)
73 {
74 	Reset(); //free data
75 
76 	vdatalen = e.vdatalen;
77 	type = e.type;
78 	idata = e.idata;
79 	idata2 = e.idata2;
80 	idata3 = e.idata3;
81 	groupnum = e.groupnum;
82 	locked = e.locked;
83 	minval = e.minval;
84 	maxval = e.maxval;
85 	oneLimit = e.oneLimit;
86 	hastooltip = e.hastooltip;
87 
88 	if (e.edc != 0)
89 	{
90 		edc = e.edc->GetCopy();
91 	}
92 	else
93 	{
94 		edc = 0;
95 	}
96 	if (e.dataname != 0)
97 	{
98 		int length = strlen(e.dataname);
99 		dataname = new char[length + 1];
100 		strcpy(dataname, e.dataname);
101 	} else
102 	{
103 		dataname = 0;
104 	}
105 	if (e.vdata != 0)
106 	{
107 		vdata = new double[vdatalen];
108 		for (int i=0; i < vdatalen; i++)
109 		{
110 			vdata[i] = e.vdata[i];
111 		}
112 	} else
113 	{
114 		vdata = 0;
115 	}
116 	if (e.tdata != 0)
117 	{
118 		int length = strlen(e.tdata);
119 		tdata = new char[length + 1];
120 		strcpy(tdata, e.tdata);
121 	}
122 	else
123 	{
124 		tdata = 0;
125 	}
126 	if (e.tooltiptext != 0)
127 	{
128 		int length = strlen(e.tooltiptext);
129 		tooltiptext = new char[length + 1];
130 		strcpy(tooltiptext, e.tooltiptext);
131 	}
132 	else
133 	{
134 		tooltiptext = 0;
135 	}
136 }
137 
Reset()138 void ElementData::Reset()
139 {
140 	locked = 0;
141 	minval = 1;
142 	maxval = 0;
143 	hastooltip = 0;
144 
145 	if (vdatalen != 0 && vdata != 0)
146 	{
147 		delete[] vdata;
148 		vdata = 0;
149 	}
150 	if (dataname != 0)
151 	{
152 		delete[] dataname;
153 		dataname = 0;
154 	}
155 	if (tdata != 0)
156 	{
157 		delete[] tdata;
158 		tdata = 0;
159 	}
160 	if (tooltiptext != 0)
161 	{
162 		delete[] tooltiptext;
163 		tooltiptext = 0;
164 	}
165 	if (edc != 0)
166 	{
167 		delete edc;
168 		edc = 0;
169 	}
170 }
171 
172 
SetVector2D(double vx,double vy,const char * name,double minvalI,double maxvalI,bool onlyLowerBorder,bool onlyUpperBorder)173 void ElementData::SetVector2D(double vx, double vy, const char* name,double minvalI, double maxvalI, bool onlyLowerBorder, bool onlyUpperBorder)
174 {
175 	Reset();
176 	SetDataName(name);
177 	type = 4+32;
178 	vdatalen = 2;
179 	vdata = new double[vdatalen];
180 	vdata[0] = vx;
181 	vdata[1] = vy;
182 	SetMinMaxVal(minvalI, maxvalI, onlyLowerBorder, onlyUpperBorder);
183 }
SetVector3D(double vx,double vy,double vz,const char * name,double minvalI,double maxvalI,bool onlyLowerBorder,bool onlyUpperBorder)184 void ElementData::SetVector3D(double vx, double vy, double vz, const char* name, double minvalI, double maxvalI, bool onlyLowerBorder, bool onlyUpperBorder)
185 {
186 	Reset();
187 	SetDataName(name);
188 	type = 4+32;
189 	vdatalen = 3;
190 	vdata = new double[vdatalen];
191 	vdata[0] = vx;
192 	vdata[1] = vy;
193 	vdata[2] = vz;
194 	SetMinMaxVal(minvalI, maxvalI, onlyLowerBorder, onlyUpperBorder);
195 }
196 
SetVector(double * v,int len,const char * name,double minvalI,double maxvalI,bool onlyLowerBorder,bool onlyUpperBorder)197 void ElementData::SetVector(double* v, int len, const char* name, double minvalI, double maxvalI, bool onlyLowerBorder, bool onlyUpperBorder)
198 {
199 	Reset();
200 	SetDataName(name);
201 	type = 4;
202 	vdatalen = len;
203 
204 	if (len > 0)
205 	{
206 		vdata = new double[vdatalen];
207 		for (int i = 0; i < vdatalen; i++)
208 		{
209 			vdata[i] = v[i];
210 		}
211 	}
212 	SetMinMaxVal(minvalI, maxvalI, onlyLowerBorder, onlyUpperBorder);
213 }
214 
SetMatrix(double * v,int rows,int cols,const char * name)215 void ElementData::SetMatrix(double* v, int rows, int cols, const char* name)
216 {
217 	Reset();
218 
219 	SetDataName(name);
220 	type = 1024;
221 	vdatalen = rows*cols;
222 
223 	idata = rows;
224 	idata2 = cols;
225 
226 	if (vdatalen > 0)
227 	{
228 		vdata = new double[vdatalen];
229 		for (int i = 0; i < vdatalen; i++)
230 		{
231 			vdata[i] = v[i];
232 		}
233 	}
234 }
235 
SetVector2DList(double * v,int n,const char * name)236 void ElementData::SetVector2DList(double* v, int n, const char* name) // $ MSax 2013-07-09 : added
237 {
238 	Reset();
239 
240 	SetDataName(name);
241 	type = 1024+4096+16384; //matrix & variable length & fixed number of columns
242 	vdatalen = 2*n;
243 
244 	idata = n;
245 	idata2 = 2; //number of columns = 2
246 
247 	if (vdatalen > 0)
248 	{
249 		vdata = new double[vdatalen];
250 		for (int i = 0; i < vdatalen; i++)
251 		{
252 			vdata[i] = v[i];
253 		}
254 	}
255 }
256 
SetMinMaxVal(double minvalI,double maxvalI,bool onlyLowerBorder,bool onlyUpperBorder)257 void ElementData::SetMinMaxVal(double minvalI, double maxvalI, bool onlyLowerBorder, bool onlyUpperBorder)
258 {
259 	// 4 cases for boundaries are possible:
260 	// oneLimit = 0:
261 	//			minval<=maxval		upper and lower boundary are active:	[...]
262 	//			minval >maxval		no boundary is active:								 ...
263 	// onLimit = 1:
264 	//			minval<=maxval		only upper boundary is active:				 ...]
265 	//			minval >maxval		only lower boundary is active:				[...
266 
267 	if(onlyLowerBorder)
268 	{
269 		minval = minvalI;
270 		maxval = minval-1;
271 	}
272 	else if(onlyUpperBorder)
273 	{
274 		maxval = maxvalI;
275 		minval = maxval-1;
276 	}
277 	else
278 	{
279 		maxval = maxvalI;
280 		minval = minvalI;
281 	}
282 
283 	oneLimit = onlyUpperBorder || onlyLowerBorder;
284 }
285 
SetInt(int num,const char * name,int minvalI,int maxvalI,bool onlyLowerBorder,bool onlyUpperBorder)286 void ElementData::SetInt(int num, const char* name, int minvalI, int maxvalI, bool onlyLowerBorder, bool onlyUpperBorder)
287 {
288 	Reset();
289 	SetDataName(name);
290 	type = 1;
291 	idata = num;
292 	double min = (double)minvalI;
293 	double max = (double)maxvalI;
294 	SetMinMaxVal(min, max, onlyLowerBorder, onlyUpperBorder);
295 }
296 
297 
SetEDC(ElementDataContainer * edcI,const char * name)298 void ElementData::SetEDC(ElementDataContainer* edcI, const char* name)
299 {
300 	Reset();
301 	SetDataName(name);
302 	type = 8192;
303 
304 	edc = edcI->GetCopy();
305 }
306 
SetEDCno_copy(ElementDataContainer * edcI,const char * name)307 void ElementData::SetEDCno_copy(ElementDataContainer* edcI, const char* name)
308 {
309 	Reset();
310 	SetDataName(name);
311 	type = 8192;
312 
313 	edc = edcI;
314 }
315 
GetEDC()316 ElementDataContainer* ElementData::GetEDC()
317 {
318 	return edc;
319 }
320 
GetEDC() const321 const ElementDataContainer* ElementData::GetEDC() const
322 {
323 	return edc;
324 }
325 
Find(const char * name) const326 int ElementDataContainer::Find(const char* name) const
327 {
328 	for (int i=1; i <= elemdata.Length(); i++)
329 	{
330 		if (_stricmp(name, elemdata(i)->GetDataName()) == 0) return i; //stricmp ignores case!!!!
331 	}
332 	return 0;
333 }
334 //$ RL 2011-6-23:[find all indices in an EDC of entries with same name.
FindAll(const char * name,TArray<int> & indices) const335 void ElementDataContainer::FindAll(const char* name, TArray<int>& indices) const
336 {
337 	indices.SetLen(0);
338 	for (int i=1; i <= elemdata.Length(); i++)
339 	{
340 		if (_stricmp(name, elemdata(i)->GetDataName()) == 0)
341 		{
342 			indices.Add(i); //stricmp ignores case!!!!
343 		}
344 	}
345 }
346 //$ RL 2011-6-23:]find all indices in an EDC of entries with same name.
347 
348 
TreeFind(const char * name) const349 const ElementData* ElementDataContainer::TreeFind(const char* name) const
350 {
351 	mystr str(name);
352 	if (str.Find('.') != -1)
353 	{
354 		int pos = 0;
355 		mystr dataname;
356 		str.GetUntil(pos, '.', dataname);
357 		mystr str_rest = str.SubString(pos+1, str.Length()-1);
358 
359 	  int i = Find(dataname);
360 		if (i && Get(i).IsEDC())
361 		{
362 			return Get(i).GetEDC()->TreeFind(str_rest.c_str());
363 		}
364 		return 0;
365 
366 	}
367 	else //no tree structure searched for
368 	{
369 	  int i = Find(name);
370 		if (i) return GetPtr(i);
371 		return 0;
372 	}
373 }
374 
TreeFind(const char * name)375 ElementData* ElementDataContainer::TreeFind(const char* name)
376 {
377 	mystr str(name);
378 	if (str.Find('.') != -1)
379 	{
380 		int pos = 0;
381 		mystr dataname;
382 		str.GetUntil(pos, '.', dataname);
383 		mystr str_rest = str.SubString(pos+1, str.Length()-1);
384 
385 	  int i = Find(dataname);
386 		if (i && Get(i).IsEDC())
387 		{
388 			return Get(i).GetEDC()->TreeFind(str_rest.c_str());
389 		}
390 		return 0;
391 
392 	}
393 	else //no tree structure searched for
394 	{
395 	  int i = Find(name);
396 		if (i) return GetPtr(i);
397 		return 0;
398 	}
399 }
400 
401 //delete an element in tree, name is e.g. "root.child1.child2.leave"; the name of the deleted object is "leave"
TreeDelete(const char * name)402 void ElementDataContainer::TreeDelete(const char* name)
403 {
404 	mystr str(name);
405 	if (str.Find('.') != -1)
406 	{
407 		int pos = 0;
408 		mystr dataname;
409 		str.GetUntil(pos, '.', dataname);
410 		mystr str_rest = str.SubString(pos+1, str.Length()-1);
411 
412 	  int i = Find(dataname);
413 		if (i && Get(i).IsEDC())
414 		{
415 			Get(i).GetEDC()->TreeDelete(str_rest.c_str());
416 			if(Get(i).GetEDC()->Length()==0) {Delete(i);}		// if it was the last leave, delete the child
417 		}
418 	}
419 	else
420 	{
421 	  int i = Find(name);
422 		if(i)	{	Delete(i);}		// delete the leave
423 	}
424 }
425 
426 extern void TIMBSWarningHandle(const char* warn, int use_instant_message_text);
427 
428 //find element, assume that it is double; if not exists use default value
429 //accepts integer and double!
TreeGetDouble(const char * name,double default_val) const430 double ElementDataContainer::TreeGetDouble(const char* name, double default_val) const
431 {
432 	const ElementData* ed = TreeFind(name);
433 	if (ed)
434 	{
435 		if (ed->IsBool()) return (double)ed->GetInt();
436 		if (ed->IsInt()) return (double)ed->GetInt();
437 		if (ed->IsDouble()) return ed->GetDouble();
438 	}
439 
440 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetDouble"),EDCWarningLevel());
441 
442 	return default_val;
443 }
444 
445 //find element, assume that it is int; if not exists use default value
446 //accepts integer and double!
TreeGetInt(const char * name,int default_val) const447 int ElementDataContainer::TreeGetInt(const char* name, int default_val) const
448 {
449 	const ElementData* ed = TreeFind(name);
450 	if (ed)
451 	{
452 		if (ed->IsBool()) return ed->GetInt();
453 		if (ed->IsInt()) return ed->GetInt();
454 		if (ed->IsDouble()) return (int)ed->GetDouble();
455 	}
456 
457 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetInt"),EDCWarningLevel());
458 
459 	return default_val;
460 }
461 
462 //find element, assume that it is int; if not exists use default value
463 //accepts integer and double!
TreeGetBool(const char * name,int default_val) const464 int ElementDataContainer::TreeGetBool(const char* name, int default_val) const
465 {
466 	const ElementData* ed = TreeFind(name);
467 	if (ed)
468 	{
469 		if (ed->IsInt()) return ed->GetInt();
470 		if (ed->IsBool()) return ed->GetInt();
471 		if (ed->IsDouble()) return (int)ed->GetDouble();
472 	}
473 
474 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetBool"),EDCWarningLevel());
475 
476 	return default_val;
477 }
478 
479 //find element, assume that it is char*; if not exists use default value
TreeGetString(const char * name,char * default_val) const480 const char* ElementDataContainer::TreeGetString(const char* name, char* default_val) const
481 {
482 	const ElementData* ed = TreeFind(name);
483 	if (ed)
484 	{
485 		if(ed->GetText())
486 		{
487 			return ed->GetText();
488 		}
489 	}
490 
491 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetString"),EDCWarningLevel());
492 
493 	return default_val;
494 }
495 
496 
TreeGetVector3D(const char * name,double & vx,double & vy,double & vz) const497 int ElementDataContainer::TreeGetVector3D(const char* name, double& vx,  double& vy,  double& vz) const
498 {
499 	const ElementData* ed = TreeFind(name);
500 	if (ed)
501 	{
502 		if (ed->IsVector() && ed->GetVectorLen() == 3)
503 		{
504 			ed->GetVector(vx, vy, vz);
505 			return 1;
506 		}
507 	}
508 
509 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetVector3D"),EDCWarningLevel());
510 
511 	return 0;
512 }
513 
TreeGetVector2D(const char * name,double & vx,double & vy) const514 int ElementDataContainer::TreeGetVector2D(const char* name, double& vx,  double& vy) const
515 {
516 	const ElementData* ed = TreeFind(name);
517 	if (ed)
518 	{
519 		if (ed->IsVector() && ed->GetVectorLen() == 2)
520 		{
521 			ed->GetVector(vx, vy);
522 			return 1;
523 		}
524 	}
525 
526 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetVector2D"),EDCWarningLevel());
527 
528 	return 0;
529 }
530 
531 //find element, assume that it is Vector; if not exists use default value
TreeGetVector(const char * name,double ** v,int & len) const532 int ElementDataContainer::TreeGetVector(const char* name, double** v, int& len) const
533 {
534 	len = 0;
535 	*v = 0;
536 	const ElementData* ed = TreeFind(name);
537 	if (ed)
538 	{
539 		if (ed->IsVector())
540 		{
541 			*v = ed->GetVector();
542 			len = ed->GetVectorLen();
543 			return 1;
544 		}
545 	}
546 
547 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetVector"),EDCWarningLevel());
548 
549 	return 0;
550 }
551 
552 //find element, assume that it is MAtrix; if not exists use default value
TreeGetMatrix(const char * name,double ** v,int & rows,int & cols) const553 int ElementDataContainer::TreeGetMatrix(const char* name, double** v, int& rows, int& cols) const
554 {
555 	rows = 0;
556 	cols = 0;
557 	*v = 0;
558 	const ElementData* ed = TreeFind(name);
559 	if (ed)
560 	{
561 		if (ed->IsMatrix())
562 		{
563 			*v = ed->GetMatrix();
564 			rows = ed->GetMatrixRows();
565 			cols = ed->GetMatrixCols();
566 			return 1;
567 		}
568 	}
569 
570 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetMatrix"),EDCWarningLevel());
571 
572 	return 0;
573 }
574 
575 //find element, assume that it is MAtrix; if not exists use default value
TreeGetVector2DList(const char * name,double ** v,int & n) const576 int ElementDataContainer::TreeGetVector2DList(const char* name, double** v, int& n) const // $ MSax 2013-07-09 : added
577 {
578 	n = 0;
579 	*v = 0;
580 	const ElementData* ed = TreeFind(name);
581 	if (ed)
582 	{
583 		if (ed->IsMatrix())
584 		{
585 			//if(ed->GetMatrixCols() != 2)
586 			//{
587 			//	ed->SetMatrixSize(n, 2);
588 			//	for (int i=1; i<=n; i++)
589 			//	{
590 			//		ed->SetMatrixVal(i,1,0);
591 			//		ed->SetMatrixVal(i,2,0);
592 			//	}
593 			//}
594 
595 			if(ed->GetMatrixCols() != 2 && ed->GetMatrixCols() !=0)
596 			{
597 				TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' has wrong dimensions"),EDCWarningLevel());
598 				return 0;
599 			}
600 
601 			*v = ed->GetMatrix();
602 			n = ed->GetMatrixRows();
603 
604 			return 1;
605 		}
606 	}
607 
608 	TIMBSWarningHandle(mystr("'")+mystr(name)+mystr("' not found in TreeGetVector2DList"),EDCWarningLevel());
609 
610 	return 0;
611 }
612 
613 
Add(const ElementData & ed)614 int ElementDataContainer::Add(const ElementData& ed)
615 {
616 	return elemdata.Add(ed.GetCopy());
617 }
618 
619 
SplitIntoTreeAndElementName(const char * name,mystr & tree,mystr & elementname)620 void ElementDataContainer::SplitIntoTreeAndElementName(const char* name, mystr& tree, mystr& elementname)
621 {
622 	mystr str(name);
623 	int pos = 0;
624 	int posold;
625 
626 	//either finds '.' and gets position of last '.', or returns -1
627 	while (pos != -1)
628 	{
629 		posold = pos;
630 		pos = str.Find(pos+1, '.');
631 	}
632 
633 	//in case of 0, the '.' is either at first position (invalid), or the '.' has not been found
634 	if (posold > 0) //split tree string into tree and elementname: str="part1.part2.part3" ==> tree = "part1.part2", elementname="part3"
635 	{
636 		tree = str.SubString(0, posold-1);
637 		elementname = str.SubString(posold+1, str.Length()-1);
638 	}
639 	else
640 	{
641 		tree = "";
642 		elementname = str;
643 	}
644 }
645 
646 	//add or replace element in EDC: double; e.g. name="tree1.leave2.data"
TreeSetDouble(const char * name,double val)647 void ElementDataContainer::TreeSetDouble(const char* name, double val)
648 {
649 	mystr tree, elementname;
650 	SplitIntoTreeAndElementName(name, tree, elementname);
651 
652 	ElementData ed;
653 	ed.SetDouble(val, elementname);
654 	TreeSet(tree, ed);
655 }
656 
657 //add or replace element in EDC: int; e.g. name="tree1.leave2.data"
TreeSetInt(const char * name,int val)658 void ElementDataContainer::TreeSetInt(const char* name, int val)
659 {
660 	mystr tree, elementname;
661 	SplitIntoTreeAndElementName(name, tree, elementname);
662 
663 	ElementData ed;
664 	ed.SetInt(val, elementname);
665 	TreeSet(tree, ed);
666 }
667 
668 //add or replace element in EDC: bool; e.g. name="tree1.leave2.data"
TreeSetBool(const char * name,int val)669 void ElementDataContainer::TreeSetBool(const char* name, int val)
670 {
671 	mystr tree, elementname;
672 	SplitIntoTreeAndElementName(name, tree, elementname);
673 
674 	ElementData ed;
675 	ed.SetBool(val, elementname);
676 	TreeSet(tree, ed);
677 }
678 
679 //add or replace element in EDC: string; e.g. name="tree1.leave2.data"
TreeSetString(const char * name,const char * val)680 void ElementDataContainer::TreeSetString(const char* name, const char* val)
681 {
682 	mystr tree, elementname;
683 	SplitIntoTreeAndElementName(name, tree, elementname);
684 
685 	ElementData ed;
686 	ed.SetText(val, elementname);
687 	TreeSet(tree, ed);
688 }
689 
690 
691 	//add or replace element in EDC with COMMENT: double; e.g. name="tree1.leave2.data"
TreeSetDoubleC(const char * name,double val,const char * comment)692 void ElementDataContainer::TreeSetDoubleC(const char* name, double val, const char* comment)
693 {
694 	mystr tree, elementname;
695 	SplitIntoTreeAndElementName(name, tree, elementname);
696 
697 	ElementData ed;
698 	ed.SetDouble(val, elementname);
699 	ed.SetToolTipText(comment);
700 	TreeSet(tree, ed);
701 }
702 
703 //add or replace element in EDC with COMMENT: int; e.g. name="tree1.leave2.data"
TreeSetIntC(const char * name,int val,const char * comment)704 void ElementDataContainer::TreeSetIntC(const char* name, int val, const char* comment)
705 {
706 	mystr tree, elementname;
707 	SplitIntoTreeAndElementName(name, tree, elementname);
708 
709 	ElementData ed;
710 	ed.SetInt(val, elementname);
711 	ed.SetToolTipText(comment);
712 	TreeSet(tree, ed);
713 }
714 
715 //add or replace element in EDC with COMMENT: bool; e.g. name="tree1.leave2.data"
TreeSetBoolC(const char * name,int val,const char * comment)716 void ElementDataContainer::TreeSetBoolC(const char* name, int val, const char* comment)
717 {
718 	mystr tree, elementname;
719 	SplitIntoTreeAndElementName(name, tree, elementname);
720 
721 	ElementData ed;
722 	ed.SetBool(val, elementname);
723 	ed.SetToolTipText(comment);
724 	TreeSet(tree, ed);
725 }
726 
727 //add or replace element in EDC with COMMENT: string; e.g. name="tree1.leave2.data"
TreeSetStringC(const char * name,const char * val,const char * comment)728 void ElementDataContainer::TreeSetStringC(const char* name, const char* val, const char* comment)
729 {
730 	mystr tree, elementname;
731 	SplitIntoTreeAndElementName(name, tree, elementname);
732 
733 	ElementData ed;
734 	ed.SetText(val, elementname);
735 	ed.SetToolTipText(comment);
736 	TreeSet(tree, ed);
737 }
738 
739 //find element, assume that it is Vector; if not exists use default value
TreeSetVectorC(const char * name,double * v,int len,const char * comment)740 void ElementDataContainer::TreeSetVectorC(const char* name, double* v, int len, const char* comment)
741 {
742 	mystr tree, elementname;
743 	SplitIntoTreeAndElementName(name, tree, elementname);
744 
745 	ElementData ed;
746 	ed.SetVector(v,len,elementname);
747 	ed.SetToolTipText(comment);
748 	TreeSet(tree, ed);
749 }
750 
TreeAdd(const char * tree,const ElementData & ed)751 void ElementDataContainer::TreeAdd(const char* tree, const ElementData& ed)
752 //void ElementDataContainer::TreeAdd(mystr tree, const ElementData& ed)
753 {
754 	mystr str(tree);
755 	if (str.Length() != 0)
756 	{
757 		int pos = 0;
758 		mystr str_rest;
759 		if (str.Find('.') != -1) //split tree string into part1 and rest: str="part1.part2.part3" ==> str_new = "part1", str_rest="part2.part3"
760 		{
761 			mystr str_new;
762 			str.GetUntil(pos, '.', str_new);
763 			str_rest = str.SubString(pos+1, str.Length()-1);
764 			str = str_new;
765 		}
766 
767 		//search if node exists
768 		int i = Find(str);
769 		if (i && Get(i).IsEDC())
770 		{
771 			Get(i).GetEDC()->TreeAdd(str_rest.c_str(), ed);
772 		}
773 		else
774 		{
775 			//create a new element data container at node
776 			ElementData ed_edc;
777 			ElementDataContainer edc_new;
778 
779 			edc_new.TreeAdd(str_rest.c_str(), ed);
780 			ed_edc.SetEDC(&edc_new, str);
781 
782 			Add(ed_edc);
783 		}
784 
785 	}
786 	else //no tree structure searched for
787 	{
788 		Add(ed);
789 	}
790 }
791 //
792 //void ElementDataContainer::TreeAdd1(mystr tree, const ElementData& ed)
793 //{
794 //	mystr str(tree);
795 //	if (str.Length() != 0)
796 //	{
797 //		int pos = 0;
798 //		mystr str_rest;
799 //		if (str.Find('.') != -1) //split tree string into part1 and rest: str="part1.part2.part3" ==> str_new = "part1", str_rest="part2.part3"
800 //		{
801 //			mystr str_new;
802 //			str.GetUntil(pos, '.', str_new);
803 //			str_rest = str.SubString(pos+1, str.Length()-1);
804 //			str = str_new;
805 //		}
806 //
807 //		//search if node exists
808 //		int i = Find(str);
809 //		if (i && Get(i).IsEDC())
810 //		{
811 //			Get(i).GetEDC()->TreeAdd2(str_rest.c_str(), ed);
812 //		}
813 //		else
814 //		{
815 //			//create a new element data container at node
816 //			ElementData ed_edc;
817 //			ElementDataContainer edc_new;
818 //
819 //			edc_new.TreeAdd2(str_rest.c_str(), ed);
820 //			ed_edc.SetEDC(&edc_new, str);
821 //
822 //			Add(ed_edc);
823 //		}
824 //
825 //	}
826 //	else //no tree structure searched for
827 //	{
828 //		Add(ed);
829 //	}
830 //}
831 //
832 //void ElementDataContainer::TreeAdd2(mystr tree, const ElementData& ed)
833 //{
834 //	mystr str(tree);
835 //	if (str.Length() != 0)
836 //	{
837 //		int pos = 0;
838 //		mystr str_rest;
839 //		if (str.Find('.') != -1) //split tree string into part1 and rest: str="part1.part2.part3" ==> str_new = "part1", str_rest="part2.part3"
840 //		{
841 //			mystr str_new;
842 //			str.GetUntil(pos, '.', str_new);
843 //			str_rest = str.SubString(pos+1, str.Length()-1);
844 //			str = str_new;
845 //		}
846 //
847 //		//search if node exists
848 //		int i = Find(str);
849 //		if (i && Get(i).IsEDC())
850 //		{
851 //			Get(i).GetEDC()->TreeAdd3(str_rest.c_str(), ed);
852 //		}
853 //		else
854 //		{
855 //			//create a new element data container at node
856 //			ElementData ed_edc;
857 //			ElementDataContainer edc_new;
858 //
859 //			edc_new.TreeAdd3(str_rest.c_str(), ed);
860 //			ed_edc.SetEDC(&edc_new, str);
861 //
862 //			Add(ed_edc);
863 //		}
864 //
865 //	}
866 //	else //no tree structure searched for
867 //	{
868 //		Add(ed);
869 //	}
870 //}
871 //
872 //void ElementDataContainer::TreeAdd3(mystr tree, const ElementData& ed)
873 //{
874 //	mystr str(tree);
875 //	if (str.Length() != 0)
876 //	{
877 //		int pos = 0;
878 //		mystr str_rest;
879 //		if (str.Find('.') != -1) //split tree string into part1 and rest: str="part1.part2.part3" ==> str_new = "part1", str_rest="part2.part3"
880 //		{
881 //			mystr str_new;
882 //			str.GetUntil(pos, '.', str_new);
883 //			str_rest = str.SubString(pos+1, str.Length()-1);
884 //			str = str_new;
885 //		}
886 //
887 //		//search if node exists
888 //		int i = Find(str);
889 //		if (i && Get(i).IsEDC())
890 //		{
891 //			Get(i).GetEDC()->TreeAdd3(str_rest.c_str(), ed);
892 //		}
893 //		else
894 //		{
895 //			//create a new element data container at node
896 //			ElementData ed_edc;
897 //			ElementDataContainer edc_new;
898 //
899 //			edc_new.TreeAdd3(str_rest.c_str(), ed);
900 //			ed_edc.SetEDC(&edc_new, str);
901 //
902 //			Add(ed_edc);
903 //		}
904 //
905 //	}
906 //	else //no tree structure searched for
907 //	{
908 //		Add(ed);
909 //	}
910 //}
911 
912 
913 
914 //set an element in the tree of edc; if the tree does not exist, build the tree and insert data; if the data exists: replace the data
TreeSet(const char * tree,const ElementData & ed,int warn_if_items_dont_exist,int copy_ToolTipText)915 void ElementDataContainer::TreeSet(const char* tree, const ElementData& ed, int warn_if_items_dont_exist, int copy_ToolTipText)
916 {
917 	mystr str = mystr(tree);
918 	if (str.Length() != 0) {str += ".";}
919 
920 	str += ed.GetDataName();
921 
922 	ElementData* edfound = TreeFind(str);
923 	if (edfound != 0)
924 	{
925 		if(edfound->IsLocked())	//$ DR 2013-04-09
926 		{
927 			TIMBSWarningHandle(mystr("The entry '") + local_warn_tree + str + mystr("' is marked as readonly in the original ElementDataContainer. The value is therefore not changed! If the entry is the variable of the parameter variation, ignore this warning.\n"),0);
928 		}
929 		else	// replace the data
930 		{
931 			if (edfound->GetType() == ed.GetType())
932 			{
933 				//copy data, but keep tooltip text
934 				mystr old_tooltip("");
935 				if (edfound->HasToolTip()) old_tooltip = edfound->GetToolTipText();
936 				edfound->CopyFrom(ed);
937 				if(!copy_ToolTipText)
938 				{
939 					edfound->SetToolTipText(old_tooltip);
940 				}
941 			}
942 			//treat int/bool/double the same; this means that the type of the old edfound is kept:
943 			else if ( (edfound->IsInt() && ed.IsBool()) || (edfound->IsInt() && ed.IsDouble()) || (edfound->IsBool() && ed.IsInt()) || (edfound->IsBool() && ed.IsDouble())
944 				|| (edfound->IsDouble() && ed.IsInt())  || (edfound->IsDouble() && ed.IsBool()) )
945 			{
946 				double val;
947 				if (ed.IsBool()) val = ed.GetBool();
948 				if (ed.IsInt()) val = ed.GetInt();
949 				if (ed.IsDouble()) val = ed.GetDouble();
950 
951 
952 				if (edfound->IsBool())   {edfound->SetBool((int)val);} //JG, do not replace data name because of case sensitivity
953 				if (edfound->IsInt())    {edfound->SetInt((int)val);} //JG, do not replace data name because of case sensitivity
954 				if (edfound->IsDouble()) {edfound->SetDouble(val);} //JG, do not replace data name because of case sensitivity
955 				//if (edfound->IsBool())   {edfound->SetBool(val, ed.GetDataName());}
956 				//if (edfound->IsInt())    {edfound->SetInt(val, ed.GetDataName());}
957 				//if (edfound->IsDouble()) {edfound->SetDouble(val, ed.GetDataName());}
958 
959 			}
960 			// write vector2d/3d into vector-ed
961 			else if ( edfound->IsVector() && ed.IsVectorXYZ() )
962 			{
963 				if (ed.GetVectorLen() == 2)
964 				{
965 					edfound->SetVector2D(ed.GetVectorVal(1), ed.GetVectorVal(2), ed.GetDataName());
966 				}
967 				if (ed.GetVectorLen() == 3)
968 				{
969 					edfound->SetVector3D(ed.GetVectorVal(1), ed.GetVectorVal(2), ed.GetVectorVal(3), ed.GetDataName());
970 				}
971 			}
972 			// write first 2 or 3 values of vector into vector2d/3d-ed
973 			else if ( edfound->IsVectorXYZ() && ed.IsVector() )
974 			{
975 				double* dummy = ed.GetVector();
976 				if (edfound->GetVectorLen() == 2 && ed.GetVectorLen() >= 2 )
977 				{
978 					edfound->SetVector2D(dummy[0], dummy[1], ed.GetDataName());
979 				}
980 				if (edfound->GetVectorLen() == 3 && ed.GetVectorLen() >= 3 )
981 				{
982 					edfound->SetVector3D(dummy[0], dummy[1], dummy[2], ed.GetDataName());
983 				}
984 				if (edfound->GetVectorLen() == 3 && ed.GetVectorLen() == 2 )
985 				{
986 					edfound->SetVector3D(dummy[0], dummy[1], 0., ed.GetDataName());
987 				}
988 			}
989 			//different types of vectors; length must be same, if vector does not have variable length
990 			else if ( edfound->IsVector() && ed.IsVector() )
991 			{
992 				//independently of exact types (intvalues, etc.), replace vector
993 				double* dummy = ed.GetVector();
994 				if ((edfound->GetVectorLen() == ed.GetVectorLen())||(edfound->IsVariableLength()))	//$ DR 2012-1: variable length added
995 				{
996 					int oldtype = edfound->GetType();
997 					edfound->SetVector(dummy, ed.GetVectorLen(), ed.GetDataName());
998 					edfound->SetType(oldtype);
999 				}
1000 				else
1001 				{
1002 					TIMBSWarningHandle(mystr("'") + local_warn_tree+mystr(ed.GetDataName())+mystr("': incompatible vector '")+mystr(edfound->GetDataName())+mystr("', check length and type of default entry!!"),EDCWarningLevel());
1003 				}
1004 			}
1005 			else if(edfound->IsMatrix() && ed.IsVector() && (edfound->IsVariableLength() || edfound->GetMatrixCols() == ed.GetVectorLen() && edfound->GetMatrixRows() == 1))
1006 			{
1007 				//$ SW 2013-11-5: added the case that the matrix has fixed column size and the vector is empty.
1008 				// matrix = vector & matrix has fixed column size => vector = [] or length(vector) == columns(matrix)
1009 				if (edfound->IsVariableLength() && edfound->IsColumnNumberFixed() && ed.GetVectorLen() != 0 && ed.GetVectorLen() != edfound->GetMatrixCols())
1010 				{
1011 					TIMBSWarningHandle(mystr("'") + local_warn_tree + mystr(ed.GetDataName()) + mystr("': incompatible vector '") + mystr(edfound->GetDataName()) + mystr("', check dimensions!"),EDCWarningLevel());
1012 				}
1013 				//matrix = vector & matrix has fixed column size && vector = []
1014 				else if (edfound->IsVariableLength() && edfound->IsColumnNumberFixed() && ed.GetVectorLen() == 0)
1015 				{
1016 					double* dummy = ed.GetVector();
1017 					int oldtype = edfound->GetType();
1018 					edfound->SetMatrix(dummy, 0, edfound->GetMatrixCols(), ed.GetDataName());
1019 					edfound->SetType(oldtype);
1020 				}
1021 				else
1022 				{
1023 					double* dummy = ed.GetVector();
1024 					int oldtype = edfound->GetType();
1025 					edfound->SetMatrix(dummy, 1, ed.GetVectorLen(), ed.GetDataName());
1026 					edfound->SetType(oldtype);
1027 				}
1028 			}
1029 			else if(edfound->IsMatrix() && ed.IsMatrix() && (edfound->IsVariableLength() || (edfound->GetMatrixCols() == ed.GetMatrixCols() && edfound->GetMatrixRows() == ed.GetMatrixRows())))
1030 			{
1031 				double* dummy = ed.GetMatrix();
1032 				int oldtype = edfound->GetType();
1033 				edfound->SetMatrix(dummy, ed.GetMatrixRows(), ed.GetMatrixCols(), ed.GetDataName());
1034 				edfound->SetType(oldtype);
1035 			}
1036 			else if(edfound->IsMatrix() && ed.IsVector() && ed.GetVectorLen() == 0)
1037 			{
1038 				// $ MSax 2013-07-11: do nothing, because ed is an empty matrix
1039 			}
1040 			else if(edfound->IsVector() && edfound->GetVectorLen() == 1 && (ed.IsDouble() || ed.IsInt()) )
1041 			{
1042 				//$ AD 2013-10-10: write a double in a length 1 vector
1043 				double dummy;
1044 				if(ed.IsDouble()) dummy = ed.GetDouble();
1045 				else if(ed.IsInt()) dummy = (double) ed.GetInt();
1046 				int oldtype = edfound->GetType();
1047 				edfound->SetVector(&dummy, 1, ed.GetDataName());
1048 				edfound->SetType(oldtype);
1049 			}
1050 			else if(edfound->IsMatrix() && edfound->GetMatrixRows() == 1 && edfound->GetMatrixCols() == 1 && (ed.IsDouble() || ed.IsInt()) )
1051 			{
1052 				//$ AD 2013-10-10: write a double in a length 1 vector
1053 				double dummy;
1054 				if(ed.IsDouble()) dummy = ed.GetDouble();
1055 				else if(ed.IsInt()) dummy = (double) ed.GetInt();
1056 				int oldtype = edfound->GetType();
1057 				edfound->SetMatrix(&dummy, 1, 1, ed.GetDataName());
1058 				edfound->SetType(oldtype);
1059 			}
1060 
1061 			else
1062 			{
1063 				//here we should put a warning, because user could set a string options to a number value
1064 				//TIMBSWarningHandle(mystr("'")+mystr(ed.GetDataName())+mystr("' is incompatible with data type of '")+mystr(edfound->GetDataName())+mystr("'!!"),EDCWarningLevel());
1065 				TIMBSWarningHandle(mystr("'")+local_warn_tree+mystr("' is incompatible with data type of '")+mystr(edfound->GetDataName())+mystr("'!!"),EDCWarningLevel());
1066 				//assert(0);
1067 			}
1068 		}
1069 	}
1070 	else
1071 	{
1072 		if (warn_if_items_dont_exist)
1073 		{
1074 			//TIMBSWarningHandle(mystr("'") + local_warn_tree + str + mystr("' added (check spelling)."), EDCWarningLevel());
1075 			TIMBSWarningHandle(mystr(" The entry '") + local_warn_tree + str + mystr("' does not exist in the original ElementDataContainer (check spelling)."), EDCWarningLevel());	//$ DR 2013-02-20 new warning, also used for skript language
1076 		}
1077 		TreeAdd(tree, ed);
1078 	}
1079 }
1080 
TreeReplaceEDCDataWith(const ElementDataContainer * edc_new,int warn_if_items_dont_exist,mystr warn_str)1081 void ElementDataContainer::TreeReplaceEDCDataWith(const ElementDataContainer* edc_new, int warn_if_items_dont_exist, mystr warn_str)
1082 {
1083 	//SetLocalWarnTree(warn_str);
1084 	TreeReplaceEDCDataWithRecursive(edc_new, warn_if_items_dont_exist);
1085 }
1086 
TreeReplaceEDCDataWithRecursive(const ElementDataContainer * edc_new,int warn_if_items_dont_exist)1087 void ElementDataContainer::TreeReplaceEDCDataWithRecursive(const ElementDataContainer* edc_new, int warn_if_items_dont_exist)
1088 {
1089 	for(int i = 1; i<=edc_new->Length(); i++)
1090 	{
1091 		ElementData ed_new = edc_new->Get(i);
1092 		mystr name = ed_new.GetDataName();
1093 		int j = Find(name);
1094 		if(j && Get(j).IsEDC()) // same variable names exist
1095 		{
1096 			Get(j).GetEDC()->TreeReplaceEDCDataWithRecursive(ed_new.GetEDC(), warn_if_items_dont_exist);// replace sub-tree
1097 		}
1098 		else
1099 		{
1100 			TreeSet("",ed_new,warn_if_items_dont_exist, 0);
1101 		}
1102 	}
1103 }
1104 
1105 //$ DR 2012-06-27
1106 //void ElementDataContainer::PrintEDCRecursive(mystr filename)
PrintEDCRecursive(ofstream & edcout)1107 void ElementDataContainer::PrintEDCRecursive(ofstream &edcout)
1108 {
1109 	//ofstream edcout(filename);
1110 	for(int i = 1; i<=Length(); i++)
1111 	{
1112 		ElementData ed_tmp = Get(i);
1113 		if(Get(i).IsEDC())
1114 		{
1115 			ElementDataContainer *edcp = Get(i).GetEDC();
1116 			edcout <<  "================== \n";
1117 			edcout << ed_tmp.GetDataName() << ":\n";
1118 			edcp->PrintEDCRecursive(edcout);
1119 		}
1120 		else
1121 		{
1122 			edcout <<  "------------------- \n";
1123 			edcout << ed_tmp.GetDataName() << ":\n";
1124 			if(ed_tmp.GetType() ==1)
1125 			{
1126 				edcout << "int = " << ed_tmp.GetInt() << "\n";
1127 			}
1128 			if(ed_tmp.GetType() ==2)
1129 			{
1130 				edcout << "double = " << ed_tmp.GetDouble() << "\n";
1131 			}
1132 			if(ed_tmp.GetType() ==4)
1133 			{
1134 				edcout << "vec = " << ed_tmp.GetVector() << "\n";
1135 			}
1136 			if(ed_tmp.GetType() == 8)
1137 			{
1138 				edcout << "txt = " << ed_tmp.GetText() << "\n";
1139 			}
1140 			if(ed_tmp.GetType() == 16)
1141 			{
1142 				edcout << "bool = " << ed_tmp.GetBool() << "\n";
1143 			}
1144 		}
1145 	}
1146 }
1147 
1148 
1149 
1150 
1151