source: Sophya/trunk/SophyaPI/PIext/pintup3d.cc@ 4042

Last change on this file since 4042 was 3505, checked in by cmv, 17 years ago

add option \"cpts\" for \"connectpoints\" rz+cmv 07/08/2008

File size: 11.1 KB
Line 
1// Peida Interactive - PI R. Ansari 97-99
2// Traceur3D (Drawer) pour NTupleInterface
3// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
4
5#include <stdio.h>
6#include "sopnamsp.h"
7#include "pintup3d.h"
8
9//#define PERC_GARDE 0.05
10
11//++
12// Class PINTuple3D
13// Lib PIext
14// include pintup3d.h
15//
16// Classe de traceur 3D à partir des données
17// d'un objet implémentant l'interface *NTupleInterface*.
18// Les objets "PINTuple3D" peuvent tracer des signes (markers)
19// éventuellement avec des barres d'erreur et une étiquette
20// pour chaque point. Si un attribut de ligne, autre que
21// "PI_NotDefLineAtt" est spécifié, les points sont connectés
22// par une ligne.
23//--
24//++
25// Links Parents
26// PIDrawer3D
27//--
28//++
29// Links Voir aussi
30// NTupleInterface
31// PINTuple
32//--
33
34//++
35// Titre Constructeur
36//--
37//++
38// PINTuple3D(NTupleInterface* nt, bool ad=false)
39// Constructeur. Si "ad == true", l'objet "nt" est détruit par
40// le destructeur de l'objet "PINTuple".
41// Note : nt doit être créé par new
42//--
43
44
45/* --Methode-- */
46PINTuple3D::PINTuple3D(NTupleInterface* nt, bool ad)
47: PIDrawer3D()
48{
49 mNT = nt;
50 mAdDO = ad;
51 aScxy = aScz = true;
52 UseSizeScale(true, 5);
53 UseColorScale(true);
54 ConnectPoints(false);
55 SelectXYZ(NULL, NULL, NULL);
56 SelectWt(NULL);
57 SelectErrBar();
58 SelectLabel(NULL);
59 SetName("NTup3DDrw");
60}
61
62PINTuple3D::~PINTuple3D()
63{
64 if (mAdDO && mNT) delete mNT;
65}
66
67//++
68// Titre Méthodes
69//--
70//++
71// void SelectXYZ(const char* px, const char* py, const char* pz)
72// Choix des noms de colonnes X,Y,Z définissant les coordonnées des points.
73// Ces trois colonnes doivent être spécifiées pour obtenir un tracé.
74// void SelectErrBar(const char* erbx=NULL, const char* erby=NULL, const char* erbz=NULL)
75// Choix des noms de colonnes pour le tracé des barres d'erreur.
76// void SelectWt(const char* pw=NULL, int nbins=10)
77// Choix du nom de colonne poids. Dans ce cas, la taille du signe
78// (marker) sera proportionnel à la valeur de cette colonne pour
79// chaque point.
80// void SelectLabel(const char* plabel)
81// Choix du nom de colonne correspondant à l'étiquette.
82//--
83
84/* --Methode-- */
85void PINTuple3D::SelectXYZ(const char* px, const char* py, const char* pz)
86{
87string name;
88if (mNT == NULL) xK = yK = zK = -1;
89if (px == NULL) xK = -1;
90else { name = px; xK = mNT->ColumnIndex(name); }
91if (py == NULL) yK = -1;
92else { name = py; yK = mNT->ColumnIndex(name); }
93if (pz == NULL) zK = -1;
94else { name = pz; zK = mNT->ColumnIndex(name); }
95}
96
97/* --Methode-- */
98void PINTuple3D::SelectWt(const char* pw)
99{
100if (pw == NULL) wK = -1;
101else { string name = pw; wK = mNT->ColumnIndex(name); }
102
103if (wK >= 0) mNT->GetMinMax(wK, wMin, wMax);
104else { wMin = 0.; wMax = 1.; }
105}
106
107/* --Methode-- */
108void PINTuple3D::SelectLabel(const char* plabel)
109{
110if (plabel == NULL) lK = -1;
111else { string name = plabel; lK = mNT->ColumnIndex(name); }
112}
113
114/* --Methode-- */
115void PINTuple3D::SelectErrBar(const char* erbx, const char* erby, const char* erbz)
116{
117string name;
118if (mNT == NULL) xebK = yebK = zebK = -1;
119if (erbx == NULL) xebK = -1;
120else { name = erbx; xebK = mNT->ColumnIndex(name); }
121if (erby == NULL) yebK = -1;
122else { name = erby; yebK = mNT->ColumnIndex(name); }
123if (erbz == NULL) zebK = -1;
124else { name = erbz; zebK = mNT->ColumnIndex(name); }
125}
126
127
128/* --Methode-- */
129void PINTuple3D::UpdateLimits()
130{
131 if (!mNT) return;
132 if (mNT->NbLines() <= 0) return;
133 if ( (xK < 0) || (yK < 0) || (zK < 0) ) return;
134
135 // Commencer par trouver nos limites
136 double xmin, xmax, ymin, ymax, zmin, zmax;
137 xmin = ymin = 9.e19;
138 xmax = ymax = -9.e19;
139 zmax = zmax = -9.e19;
140 mNT->GetMinMax(xK, xmin, xmax);
141 mNT->GetMinMax(yK, ymin, ymax);
142 mNT->GetMinMax(zK, zmin, zmax);
143
144 ComputeScaleFactor(xmin, xmax, ymin, ymax, zmin, zmax,
145 aScxy, aScz, mScy, mScz);
146
147 // cout << " DEBUG - NTup3D X:" << XMin3() << "-" << XMax3() " s=" << mScx
148 // << " Y:" YMin3() << "-" << YMax3() << "
149 xmin *= mScx; xmax *= mScx;
150 ymin *= mScy; ymax *= mScy;
151 zmin *= mScz; zmax *= mScz;
152// Centre du champ en C = (xmin+xmax)/2., (ymin+ymax)/2 (zmin+zmax)*0.5
153// Distance D = Max(xmax-xmin,ymin-ymax)*2
154// Observateur en O = X+D, Yc+2*D
155 double D = xmax-xmin;
156 if (D < (ymax-ymin)) D = ymax-ymin;
157 D *= 1.4;
158
159 Set3DView((xmin+xmax)/2., (ymin+ymax)/2, (zmin+zmax)/2.,
160 (xmin+xmax)/2.+D , (ymin+ymax)/2.-2.5*D , zmin+(zmax-zmin)*0.85, 0.25, 0.25);
161
162 Set3DBox(xmin, xmax, ymin, ymax, zmin, zmax, mScx, mScy, mScz);
163
164 /*
165 x3Min = xmin; // - PERC_GARDE*(xmax-xmin);
166 x3Max = xmax; // + PERC_GARDE*(xmax-xmin);
167 y3Min = ymin; // - PERC_GARDE*(ymax-ymin);
168 y3Max = ymax; // + PERC_GARDE*(ymax-ymin);
169 z3Min = zmin; // - PERC_GARDE*(zmax-zmin);
170 z3Max = zmax; // + PERC_GARDE*(zmax-zmin);
171 */
172
173
174// printf("PINTuple3D::UpdateLimits() : %g .. %g %g .. %g %g .. %g (%g) \n", xmin,xmax,ymin,ymax,zmin,zmax,D);
175// printf("PINTuple3D::UpdateLimits() : %g %g %g << %g %g %g \n",
176// (xmin+xmax)/2., (ymin+ymax)/2, (zmin+zmax)*0.5,
177// (xmin+xmax)/2.+D , (ymin+ymax)/2.+2.*D , zmin+(zmax-zmin)*0.1);
178}
179
180
181/* --Methode-- */
182void PINTuple3D::Draw(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax)
183{
184double xp,yp,zp,wp,xer,yer,zer;
185double xl,yl,zl;
186int nok;
187
188// On trace les axes - En attendant de faire mieux - Reza 8/12/98
189if (axesFlags != kAxesNone) DrawAxes(g);
190
191if (!mNT) return;
192if ( (xK < 0) || (yK < 0) || (zK < 0) ) return;
193
194#if defined(CC_HAS_RTTI_SUPPORT)
195PIGraphic3D* g3 = dynamic_cast<PIGraphic3D*>(g);
196#else
197PIGraphic3D* g3 = (PIGraphic3D*)(g);
198#endif
199
200if (GetGraphicAtt().GetLineAtt() == PI_NotDefLineAtt) g3->SelLine(PI_ThinLine);
201
202// Pour tracer des markers avec taille fonction de Wt (poids)
203double dw = (wMax-wMin)/nWbins;
204if (dw < 1.e-19) dw = 1.e-19;
205// Pour tracer des markers avec couleur en fonction de Wt (poids)
206PIColorMap * cmap = NULL;
207double dwc = 1.;
208double nwc = 1.;
209bool revcmap;
210CMapId mcmapid = GetGraphicAtt().GetColMapId(revcmap);
211if( colorScale && (wK >= 0) && (mcmapid != CMAP_OTHER) ) {
212 cmap = new PIColorMap(mcmapid);
213 cmap->ReverseColorIndex(revcmap);
214 nwc = cmap->NCol();
215 dwc = (wMax-wMin)/nwc;
216}
217
218int msz,sz;
219
220PIMarker mmrk = GetGraphicAtt().GetMarker();
221PIMarker mrk;
222if (wK >= 0) mrk = (mmrk != PI_NotDefMarker) ? mmrk : PI_CircleMarker;
223else mrk = (mmrk != PI_NotDefMarker) ? mmrk : PI_DotMarker;
224msz = GetGraphicAtt().GetMarkerSz();
225if (msz < 1) msz = 1;
226g->SelMarker(msz, mrk);
227
228nok = 0;
229xp = yp = zp = xl = yl = zl = 0;
230for (int i=0; i<mNT->NbLines(); i++) {
231 xl = xp; yl = yp; zl = zp;
232 xp = mNT->GetCell(i, xK);
233 yp = mNT->GetCell(i, yK);
234 zp = mNT->GetCell(i, zK);
235
236// Taille - couleur de marker en fonction du poids
237 if (wK >= 0) wp = mNT->GetCell(i, wK);
238 if (mrkSzScale && (wK >= 0)) { // Changement de taille
239 sz = (int)((wp-wMin)/dw);
240 if (sz < 0) sz = 0;
241 if (sz > nWbins) sz = nWbins;
242 sz += msz;
243 if (sz < 2) g->SelMarker(sz, PI_DotMarker);
244 else g->SelMarker(sz, mrk);
245 }
246// Couleur du marker en fonction du poids
247 if( colorScale && (wK >= 0) && cmap ) {
248 int cid = (int)((wp-wMin)/dwc);
249 if (cid < 0) cid = 0;
250 if (cid >= nwc) cid = nwc-1;
251 g->SelForeground(*cmap, cid);
252 }
253
254 if ( (i > 0) && connectPts ) // On relie les points ...
255 g3->DrawLine3D(ScaleX(xl), ScaleY(yl), ScaleZ(zl), ScaleX(xp), ScaleY(yp), ScaleZ(zp));
256 nok++;
257 if ( xebK >= 0 ) {
258 xer = mNT->GetCell(i, xebK);
259 g3->DrawLine3D(ScaleX(xp-xer), ScaleY(yp), ScaleZ(zp), ScaleX(xp+xer), ScaleY(yp), ScaleZ(zp) );
260 }
261 if ( yebK >= 0 ) {
262 yer = mNT->GetCell(i, yebK);
263 g3->DrawLine3D(ScaleX(xp), ScaleY(yp-yer), ScaleZ(zp), ScaleX(xp), ScaleY(yp+yer), ScaleZ(zp) );
264 }
265 if ( zebK >= 0 ) {
266 zer = mNT->GetCell(i, zebK);
267 g3->DrawLine3D(ScaleX(xp), ScaleY(yp), ScaleZ(zp-zer), ScaleX(xp), ScaleY(yp), ScaleZ(zp+zer));
268 }
269 // Trace du marker
270 if ((wK >= 0)||(lK < 0)||(mmrk != PI_NotDefMarker))
271 g3->DrawMarker3D(ScaleX(xp), ScaleY(yp), ScaleZ(zp));
272 // Trace eventuel du label
273 if (lK >= 0) g3->DrawString3D(ScaleX(xp), ScaleY(yp), ScaleZ(zp),
274 mNT->GetCelltoString(i, lK).c_str());
275}
276
277return;
278}
279
280/* La methode DecodeOptionString permet de decoder un ensemble d'options
281 et de parametre d'affichage specifie sous forme d'un vecteur de string.
282 Si rmdecopt == true, les options decodees sont supprimees du vecteur
283 de string fourni en entree - ce qui permet l'enchainement eventuel
284 de plusieurs decodages de string.
285 Les options peuvent etre sous forme de flag : "connectpoints" "noconnectpoints"
286 ou plus complexes, par exemple "dynamic=-3,3"
287 Rc: La methode renvoie le nombre d'options decodees
288*/
289
290/* --Methode-- */
291int PINTuple3D::DecodeOptionString(vector<string> & opt, bool rmdecopt)
292{
293 int optsz1 = opt.size();
294 if(optsz1<1) return(0);
295 // On appelle d'abord le decodage de la classe PIDrawer de laquelle
296 // on herite. (Pas obligatoire) on decode donc ici les attributs de
297 // couleur, fontes ...
298 int ndec1 = PIDrawer3D::DecodeOptionString(opt, rmdecopt);
299 if(optsz1-ndec1<1) return(ndec1); // si tout a ete decode
300
301 vector<string> udopt; // On gardera ici les options non decodees
302 unsigned int k = 0;
303 int ndec = opt.size();
304 for( k=0; k<opt.size(); k++ ) {
305 string opts = opt[k];
306 if (opts == "connectpoints") ConnectPoints(true);
307 else if (opts == "cpts") ConnectPoints(true);
308 else if (opts == "noconnectpoints") ConnectPoints(false);
309 else if (opts == "colorscale") UseColorScale(true);
310 else if (opts == "nocolorscale") UseColorScale(false);
311 else if (opts == "sizescale") UseSizeScale(true);
312 else if (opts == "nosizescale") UseSizeScale(false);
313 else if (opts.substr(0,10) == "sizescale=") {
314 int nbn = atoi(opts.substr(10).c_str());
315 UseSizeScale(true, nbn);
316 }
317 else {
318 // Si option non decode
319 ndec--;
320 // S'il faut supprimer les options decodees
321 if (rmdecopt) udopt.push_back(opts);
322 }
323 }
324 // S'il faut supprimer les options decodees, on remplace l'argument opt
325 // par le vecteur des options non decodees.
326 if (rmdecopt) opt = udopt;
327 return(ndec+ndec1);
328}
329
330int PINTuple3D::OptionToString(vector<string> & opt) const
331{
332 PIDrawer3D::OptionToString(opt);
333
334 if(connectPts) opt.push_back("connectpoints");
335 else opt.push_back("noconnectpoints");
336
337 if(colorScale) opt.push_back("colorscale");
338 else opt.push_back("nocolorscale");
339
340 if(mrkSzScale) {
341 char str[256];
342 if(nWbins>0) {sprintf(str,"sizescale=%d",nWbins); opt.push_back(str);}
343 else opt.push_back("sizescale");
344 } else opt.push_back("nosizescale");
345
346 return 1;
347}
348
349/* La methode GetOptionsHelpInfo(string& info) renvoie une chaine
350 avec la description des options comprises par ce drawer
351 Note: Il est preferable de ne pas initialiser la chaine
352 string info au depart, afin de permettre de mettre bout a
353 bout les aides de differents Drawer */
354
355/* --Methode-- */
356void PINTuple3D::GetOptionsHelpInfo(string& info)
357{
358info += " ---- PINTuple3D options help info : \n" ;
359info += " connectpoints: The points are connected by a line \n";
360info += " noconnectpoints (this is the default) \n";
361info += " colorscale/nocolorscale (Use color scale for weight) \n";
362info += " sizescale/sizescale=nbins/nosizescale (Use marker size for weight) \n";
363// On recupere ensuite la chaine info de la classe de base
364PIDrawer3D::GetOptionsHelpInfo(info);
365return;
366}
367
Note: See TracBrowser for help on using the repository browser.