CGEM BOSS 6.6.5.g
BESIII Offline Software System
Loading...
Searching...
No Matches
Mdc2DWire.cxx
Go to the documentation of this file.
1#include <TString.h>
2#include <TColor.h>
3#include <iostream>
4#include "math.h"
5#include "TMath.h"
7#include "BesVisLib/BesView.h"
9
10using namespace std;
11
12#ifndef __CINT__
14#endif
15
16//_____________________________________________________
17
19
20}
21
22//_____________________________________________________
23
24Mdc2DWire::Mdc2DWire(const char* name,
25 const char* title,
26 Double_t rmin,
27 Double_t rmax,
28 Double_t dz,
29 Double_t phi,
30 Double_t *center )
31{
32
33 SetName(name);
34 SetTitle(title);
35 fTip = 0;
36 fTube = 0; //Long Peixun's update: Add fTube initialization
37 fHighlighted = false;
38 fFired = false;
39 fColorfulWire = false;
40 fWireType = 1; // axial wire
41 evTime = 0;
42 //Long Peixun's update: Add flags initialization
43 qOverflow = false;
44 timeChannel = 0;
45 chargeChannel = 0;
46
47 Double_t r = 0.25*(rmax-rmin);
48 fWireCircle = new BesCircle2D(name, title, 0.0, r, &center[0]);
49
50 Double_t dx = fabs(r*cos(phi));
51 Double_t dy = fabs(r*sin(phi));
52 Double_t P[12] = { center[0] - dx, center[1] - dy, center[2] - dz,
53 center[0] + dx, center[1] + dy, center[2] - dz,
54 center[0] - dx, center[1] - dy, center[2] + dz,
55 center[0] + dx, center[1] + dy, center[2] + dz
56 };
57
58 fWireCone = new BesPolygon2D(name, title, 4, P);
59
60 Init();
61}
62
63//_____________________________________________________
64
65Mdc2DWire::Mdc2DWire(const char* name, const char* title, Int_t N, Double_t *P)
66{
67 SetName(name);
68 SetTitle(title);
69 fTip = 0;
70 fHighlighted = false;
71 fFired = false;
72 fColorfulWire = false;
73 fWireType = 2; // stereo wire
74
75 Double_t *tubeP = &P[3*N/2]; // east four points, P4~P7
76 fTube = new BesPolygon2D(name, title, N/2, tubeP);
77 fWireCircle = 0;
78 fWireCone = 0;
79
80 for (Int_t i = 0; i < 3; i++) {
81 fWestHole[i] = (P[i] + P[3+i] + P[6+i] + P[9+i] )/4.0; // (P0+P1+P2+P3)/4
82 fEastHole[i] = (P[12+i] + P[15+i] + P[18+i] + P[21+i])/4.0; // (P4+P5+P6+P7)/4
83 }
84 TVector3 westVec(fWestHole[0], fWestHole[1], fWestHole[2]);
85 TVector3 eastVec(fEastHole[0], fEastHole[1], fEastHole[2]);
86 fWestPhi = westVec.Phi() * TMath::RadToDeg();
87 fEastPhi = eastVec.Phi() * TMath::RadToDeg();
88 if (fWestPhi < 0.0) fWestPhi += 360.0;
89 if (fEastPhi < 0.0) fEastPhi += 360.0;
90
91 // ------XY------
92 Double_t rMax = sqrt( (P[4*3] -P[7*3]) * (P[4*3]-P[7*3]) +
93 (P[4*3+1]-P[7*3+1]) * (P[4*3+1]-P[7*3+1]) +
94 (P[4*3+2]-P[7*3+2]) * (P[4*3+2]-P[7*3+2]) ) / 2.0;
95
96 Double_t rMinRatio = 0.0001; // min bubble radius = rMinRatio * rMax;
97 Double_t rMaxRatio = 0.8;//0.6; // 0.4//yzhang
98
99 Double_t newP[12];
100 Double_t edge = rMaxRatio*0.0001; //*0.85
101 for (Int_t i = 0; i < 3; i++) {
102 newP[i] = (0.5+edge*rMinRatio)*(P[i]+P[3+i])*0.5
103 + (0.5-edge*rMinRatio)*(P[6+i]+P[9+i])*0.5; // near center of P0+P1
104 newP[3+i] = (0.5-edge*rMinRatio)*(P[i]+P[3+i])*0.5
105 + (0.5+edge*rMinRatio)*(P[6+i]+P[9+i])*0.5; // near center of P2+P3
106 newP[6+i] = (0.5+edge*rMaxRatio)*(P[12+i]+P[15+i])*0.5
107 + (0.5-edge*rMaxRatio)*(P[18+i]+P[21+i])*0.5; // near center of P4+P5
108 newP[9+i] = (0.5-edge*rMaxRatio)*(P[12+i]+P[15+i])*0.5
109 + (0.5+edge*rMaxRatio)*(P[18+i]+P[21+i])*0.5; // near center of P6+P7
110 }
111 fWireCone = new BesPolygon2D("WireCone", "WireCone", 4, &newP[0]);
112
113 fWireCircle =
114 new BesCircle2D("WireBubble", "WireBubble", 0.0, rMaxRatio*rMax, &fEastHole[0]);
115
116 // ------ZR------
117 fZRPosMarker2D =
118 new BesMarker2D("MdcZRPos", "MdcZRPos", fEastHole[0], fEastHole[1], fEastHole[2]);
119
120 Init();
121}
122
123//_____________________________________________________
124
126
127 //Long Peixun's update: remove "if"
128 delete fTube;
129 delete fWireCircle;
130 delete fWireCone;
131 delete fZRPosMarker2D;
132 delete fTip;
133}
134
135//_____________________________________________________
136
138
139 SetStyle();
140
141 fTip = new BesPaveText(0, 0, 0.1, 0.1);
142 CloseInfo();
143}
144
145//_____________________________________________________
146
148{
149 lcTube = kBlack; // grey;
150 lwTube = 1;
151 fcTube = kBlack; // grey 15;
152 fsTube = 4000;
153
154 lcWire = 15;
155 if (fWireType == 1) lcWire = kGreen;
156 if (fWireType == 2) lcWire = kBlue;
157 lwCircle = 1;
158 lwCone = 1;
159 fcCircle = kWhite;
160 fcCone = 0;
161 fsCircle = 1001;
162 fsCone = 0;
163
164 lcWireFired = kRed;
165 lwCircleFired = 2;//yzhang 2;
166 lwConeFired = 2;
167 fcCircleFired = 1004; //kBlack;
168 fcConeFired = kBlack;
169 fsCircleFired = 1001;//solid
170 fsConeFired = 3001;
171
172 lcWireHL = kMagenta;//yzhang lcWire;
173 lwCircleHL = 2;
174 lwConeHL = 2;
175 fcCircleHL = kMagenta;//yzhang kBlack;
176 fcConeHL = kRed;
177 fsCircleHL = 1001;
178 fsConeHL = 4000;
179
180 sizeMarker = 4;
181 cMarker = kBlue;
182 cMarkerFired = kRed; // color of fired marker
183 cMarkerHL = cMarker; // cMarkerFired;
184 sMarker = 24;
185 sMarkerFired = 20; // style of fired marker
186 sMarkerHL = 25; // style of highlighted marker
187}
188
190{
191 fInfoCon.clear();
192 fTip->DeleteText();
193}
194
196{
197 if (fTip) {
198 fTip->Clear();
199
200 if (fInfoCon.size() == 0) fInfoCon.push_back(GetTitle());
201 fTip->SetText(fInfoCon);
202 }
203 else
204 cout << "Mdc2DWire::CloseInfo, not initialized" << endl;
205}
206
207//_____________________________________________________
208
209Int_t Mdc2DWire::DistancetoPrimitive(Int_t px, Int_t py) {
210 BesView *view = dynamic_cast<BesView*>(gPad->GetView());
211 if (view->GetViewType() & kXYView) {
212 return fWireCircle->DistancetoPrimitive(px, py);
213 }
214 else if (view->GetViewType() & kZRView) {
215 if (fZRPosMarker2D) {
216 //Long Peixun's update: Remove duplicate code
217
218 //This bug can be avoid by changing the initialize order of subdetectors
219 // if ((unsigned long long)(fZRPosMarker2D) & 0xFFFFFFFF00000000)
220 // {
221 // cout << this << " " << fZRPosMarker2D << endl;
222 // }
223
224 return fZRPosMarker2D->DistancetoPrimitive(px, py);
225 }
226 }
227
228 return 999;
229}
230
231//_____________________________________________________
232
233void Mdc2DWire::ExecuteEvent(Int_t event, Int_t px, Int_t py) {
234
235 BesView *view = dynamic_cast<BesView*>(gPad->GetView());
236
237 if (gBesCursor->GetType() == kBesHand) {
238 if (view) view->ExecuteEvent(event, px, py);
239 }
240 else if (gBesCursor->GetType() == kBesPick){
241
242 if (gPad) gPad->SetCursor(kPointer);
243
244 Int_t origColor = 1;
245
246 switch (event) {
247
248 case kMouseEnter :
249
250 if ( fWireCircle ) origColor = fWireCircle->GetFillColor();
251 if ( fZRPosMarker2D ) origColor = fZRPosMarker2D->GetMarkerColor();
252 this->SetHighlighted(true);
253
254 if (this->IsFired() || view->GetVisMdcWires()) {
255 Draw("WIRE,SAME");
256
257 fTip->SetPos(px, py);
258 view->UpdateView(0);
259
260 //Long Peixun's update: If ShowInfo is not checked, don't show tip text.
261 if (gBesCursor->GetShowInfo()) fTip->Draw("BR,SAME"); // "BR,ARC,SAME"
262 gPad->Modified();
263 gPad->Update();
264 }
265 break;
266
267 case kMouseLeave:
268
269 if (this->IsHighlighted()) {
270 this->SetHighlighted(false);
271 if (view->GetVisMdcWires()) Draw("WIRE,SAME");
272
273 view->UpdateView(0);
274 gPad->Modified();
275 gPad->Update();
276 }
277 break;
278 }
279
280 }
281}
282
283//_____________________________________________________
284
285void Mdc2DWire::Draw(Option_t *option) {
286 //
287 // Mdc2DWire draw function
288 TString opt = option;
289 opt.ToUpper();
290
291 AppendPad(option);
292}
293
294//_____________________________________________________
295
296void Mdc2DWire::Paint(Option_t *option) {
297
298 TString opt = option;
299 opt.ToUpper();
300
301 BesView *view = dynamic_cast<BesView*>(gPad->GetView());
302
303 //gStyle->SetPalette(1);
304 if (view->GetViewType() & kXYView) {
305
306 Double_t wcCenter[3], ncCenter[3];
307 fWireCircle->GetCenter(&wcCenter[0]);
308 view->WCtoNDC(wcCenter, &ncCenter[0]);
309 Double_t x1, y1, x2, y2;
310 Double_t d = 0.05;
311 gPad->GetRange(x1, y1, x2, y2);
312
313 // Only draw wire in pad range
314 if (ncCenter[0] > x1-d && ncCenter[0] < x2+d &&
315 ncCenter[1] > y1-d && ncCenter[1] < y2+d) {
316 if (opt.Contains("TUBE") && fTube ) {
317 fTube->SetLineColor(lcTube);
318 fTube->SetLineWidth(lwTube);
319 fTube->SetFillColor(fcTube);
320 fTube->SetFillStyle(fsTube);
321
322 fTube->Paint();
323 }
324
325 if (this->IsFired()) {
326 if (fWireCircle) {
327 fWireCircle->SetLineColor(lcWireFired);
328 fWireCircle->SetLineWidth(lwCircleFired);
329 fWireCircle->SetFillColor(fcCircleFired);
330 fWireCircle->SetFillStyle(fsCircleFired);
331 }
332 if (fWireCone) {
333 fWireCone->SetLineColor(lcWireFired);
334 fWireCone->SetLineWidth(lwConeFired);
335 fWireCone->SetFillColor(fcConeFired);
336 fWireCone->SetFillStyle(fsConeFired);
337 }
338 }
339 else {
340 if (fWireCone) {
341 fWireCone->SetLineColor(lcWire);
342 fWireCone->SetLineWidth(lwCone);
343 fWireCone->SetFillColor(fcCone);
344 fWireCone->SetFillStyle(fsCone);
345 }
346 if (fWireCircle) {
347 fWireCircle->SetLineColor(lcWire);
348 fWireCircle->SetLineWidth(lwCircle);
349 fWireCircle->SetFillColor(fcCircle);
350 fWireCircle->SetFillStyle(fsCircle);
351 }
352 }
353
354 if (this->IsHighlighted()) {
355 if (fWireCircle) {
356 fWireCircle->SetLineColor(lcWireHL);
357 fWireCircle->SetLineWidth(lwCircleHL);
358 fWireCircle->SetFillColor(fcCircleHL);
359 fWireCircle->SetFillStyle(fsCircleHL);
360 }
361 if (fWireCone) {
362 fWireCone->SetLineColor(lcWireHL);
363 fWireCone->SetLineWidth(lwConeHL);
364 fWireCone->SetFillColor(fcConeHL);
365 fWireCone->SetFillStyle(fsConeHL);
366 }
367 }
368 if (opt.Contains("WIRE")) {
369 //Long Peixun's update: Only draw fired wires' cone
370 if (IsFired()) fWireCone->Paint(); //Long Peixun's update: Draw colorful wires' cone
371 if (fWireCircle) fWireCircle->Paint();
372 }
373 }
374 }
375
376 if (view->GetViewType() & kZRView) {
377 if (HasZRSection()) {
378 fZRPosMarker2D->SetWCX(fZRSectionPos[0]);
379 fZRPosMarker2D->SetWCY(fZRSectionPos[1]);
380 fZRPosMarker2D->SetWCZ(fZRSectionPos[2]);
381 fZRPosMarker2D->SetMarkerColor(cMarker);
382 fZRPosMarker2D->SetMarkerStyle(sMarker);
383 fZRPosMarker2D->SetMarkerSizeMultiple(sizeMarker);
384
385 if (this->IsFired()) {
386 if (fZRPosMarker2D) {
387 fZRPosMarker2D->SetMarkerColor(cMarkerFired);
388 fZRPosMarker2D->SetMarkerStyle(sMarkerFired);
389 }
390 }
391 else {
392 if (fZRPosMarker2D) {
393 fZRPosMarker2D->SetMarkerColor(cMarker);
394 fZRPosMarker2D->SetMarkerStyle(sMarker);
395 }
396 }
397
398 if (this->IsHighlighted()) {
399 if (fZRPosMarker2D) {
400 fZRPosMarker2D->SetMarkerColor(cMarkerHL);
401 fZRPosMarker2D->SetMarkerStyle(sMarkerHL);
402 }
403 }
404
405 if (opt.Contains("WIRE")) {
406 if (fZRPosMarker2D) fZRPosMarker2D->Paint();
407 }
408 }
409 }
410}
411
412//_____________________________________________________
413
414char *Mdc2DWire::GetObjectInfo(Int_t px, Int_t py) const {
415
416 BesView *view = dynamic_cast<BesView*>(gPad->GetView());
417 if (view) return view->GetObjectInfo(px, py);
418 else return TObject::GetObjectInfo(px, py);
419}
420
421//_____________________________________________________
422
424{
425 if (fWireType != 2) return false;
426
427 bool flag = false;
428 BesView *view = dynamic_cast<BesView*>(gPad->GetView());
429 Double_t viewPhi = view->GetLongitude();
430 viewPhi = Range360(viewPhi);
431 //if (GetName() == TString("Layer0Wire0")) cout << "view " << viewPhi << endl;
432
433 Double_t zrPhi = viewPhi-90.0;
434 zrPhi = Range360(zrPhi);
435 //if (GetName() == TString("Layer0Wire0")) cout << zrPhi << endl;
436
437 for (Int_t i = 0; i < 2; i++) {
438 if (i==1) {
439 zrPhi += 180.0;
440 zrPhi = Range360(zrPhi);
441 }
442
443 if ( fabs(fEastPhi-fWestPhi) < 180.0 ) { // no cross phi=0.0
444 if ( (fEastPhi-zrPhi)*(fWestPhi-zrPhi) > 0.0 ) flag = false;
445 else {
446 Double_t factor = fabs( (fEastPhi-zrPhi)/(fEastPhi-fWestPhi) );
447 for (Int_t i = 0; i < 3; i++) {
448 fZRSectionPos[i] = factor*fWestHole[i] + (1.0-factor)*fEastHole[i];
449 }
450 flag = true;
451 break;
452 }
453 }
454 else { // cross phi=0.0
455 if ( (fEastPhi-zrPhi)*(fWestPhi-zrPhi) < 0.0 ) flag = false;
456 else { // range 0~360 -> -180~180
457 Double_t tempEastPhi = fEastPhi;
458 if (tempEastPhi >= 180.0) tempEastPhi -= 360.0;
459 Double_t tempWestPhi = fWestPhi;
460 if (tempWestPhi >= 180.0) tempWestPhi -= 360.0;
461 Double_t tempZRPhi = zrPhi;
462 if (tempZRPhi >= 180.0) tempZRPhi -= 360.0;
463
464 Double_t factor = fabs( (tempEastPhi-tempZRPhi)/(tempEastPhi-tempWestPhi) );
465 for (Int_t i = 0; i < 3; i++) {
466 fZRSectionPos[i] = factor*fWestHole[i] + (1.0-factor)*fEastHole[i];
467 }
468 flag = true;
469 break;
470 }
471 }
472 }
473
474 return flag;
475}
476
477//_____________________________________________________
478
479Double_t Mdc2DWire::Range360(Double_t input)
480{
481 if (input >= 360.0) {
482 do {
483 input -= 360.0;
484 }
485 while (input >= 360.0);
486 }
487 else if (input < 0.0) {
488 do {
489 input += 360.0;
490 }
491 while (input < 0.0);
492 }
493
494 return input;
495}
496
497//_____________________________________________________
498
500{
501 mdcTime = time;
502}
503
504//_____________________________________________________
505
506void Mdc2DWire::SetCharge(Double_t charge)
507{
508 mdcCharge = charge;
509}
510
511//_____________________________________________________
512
513void Mdc2DWire::SetQOverflow(Bool_t qOvfl)
514{
515 qOverflow = qOvfl;
516}
517
518//_____________________________________________________
519
521{
522 evTime = time;
523}
524
525//_____________________________________________________
526//Long Peixun's update: raw channel data for mdc hits display
528{
529 timeChannel = tc;
530}
532{
533 chargeChannel = cc;
534}
535
536//_____________________________________________________
537
538void Mdc2DWire::SetColorfulWire(Bool_t colorfulWire, Bool_t subEvTime)
539{
540 fColorfulWire = colorfulWire;
541 if(fColorfulWire){
542 //yzhang change LINE COLOR of fired mdc wires
543 //n color bin = 50, time of max bin is 2000
544 //time max value = 1943.8125 ~ 2000 ns
545 //no time info color is kGray
546 //time > 2000 && time <=10000, color is kBlack
547 int tempColor;
548 if(subEvTime){
549 // raw time - event start time
550 double tempMdcTime = mdcTime - evTime;
551 if(fabs(evTime)>0.0001) tempMdcTime += 230;
552 if(tempMdcTime>10000) {
553 tempColor = kGray;
554 }else if(tempMdcTime>2000&&tempMdcTime<=10000){
555 tempColor = kRed;
556 }else if(tempMdcTime<-10){
557 tempColor = kWhite;
558 }else{
559 tempColor = 51 + (int) (tempMdcTime/40);
560 }
561 }else{
562 //raw time
563 if(mdcTime>10000) {
564 tempColor= kGray;
565 }else if(mdcTime>2000&&mdcTime<=10000){
566 tempColor = kRed;
567 }else{
568 tempColor = 51 + (int) (mdcTime/40);
569 }
570 }
571 lcWireFired = tempColor;
572 //std::cout<< " mdcTime "<<mdcTime <<" evTime "<< evTime << " t-t0 "<< mdcTime - evTime +230<< " lcWireFired " << lcWireFired <<std::endl;
573
574 //yzhang change FILL COLOR of fired mdc wires
575 //n color bin = 50, charge of max bin is 2000
576 //charge max value = 29783 ~ 30000
577 //adc> 2000&&<=30000 color is kBlack
578 //no adc color is kGray
579 if(mdcCharge>30000){
580 tempColor = kGray;
581 }else if(mdcCharge>2000&&mdcCharge<=30000){
582 tempColor = kRed;
583 }else {
584 tempColor = 51 + (int) (mdcCharge/40);
585 }
586 if(qOverflow) { tempColor = kBlack; }
587 fcCircleFired = tempColor;
588 //std::cout<< " mdcCharge "<<mdcCharge<<" ovfl "<<qOverflow<<" fcCircleFired " << fcCircleFired<< std::endl;
589 }else{
590 lcWireFired = kRed;
591 fcCircleFired = 1004;
592 }
593}
double sin(const BesAngle a)
Definition: BesAngle.h:210
double cos(const BesAngle a)
Definition: BesAngle.h:213
@ kBesHand
Definition: BesCursor.h:15
@ kBesPick
Definition: BesCursor.h:14
R__EXTERN BesCursor * gBesCursor
Definition: BesCursor.h:40
@ kXYView
Definition: BesStatus.h:15
@ kZRView
Definition: BesStatus.h:16
double P(RecMdcKalTrack *trk)
gr SetTitle("BbLum_000XXXX")
Double_t time
ClassImp(Mdc2DWire) Mdc2DWire
Definition: Mdc2DWire.cxx:13
virtual void Paint(Option_t *option="")
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Definition: BesCircle2D.cxx:78
virtual void GetCenter(Double_t *center)
Bool_t GetShowInfo()
Definition: BesCursor.h:35
EBESCursorType GetType()
Definition: BesCursor.h:32
virtual void SetWCY(Float_t input)
Definition: BesMarker2D.h:45
virtual void SetMarkerSizeMultiple(Int_t input)
Definition: BesMarker2D.h:34
virtual void Paint(Option_t *option="")
virtual void SetWCZ(Float_t input)
Definition: BesMarker2D.h:46
virtual void SetWCX(Float_t input)
Definition: BesMarker2D.h:44
virtual void SetText(std::vector< TString > infoCon)
Definition: BesPaveText.cxx:35
virtual void SetPos(Int_t px, Int_t py)
Definition: BesPaveText.cxx:86
virtual void Paint(Option_t *option="")
Double_t GetLongitude()
Definition: BesTView.h:95
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)
Definition: BesView.cxx:824
virtual void UpdateView(Bool_t resetview=kFALSE)
Definition: BesView.cxx:753
Bool_t GetVisMdcWires()
Definition: BesView.h:133
virtual char * GetObjectInfo(Int_t px, Int_t py) const
Definition: BesView.cxx:965
EBESViewType GetViewType()
Definition: BesView.h:74
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Definition: BesView.cxx:451
void SetChargeChannel(UInt_t cc)
Definition: Mdc2DWire.cxx:531
virtual void ClearInfo()
Definition: Mdc2DWire.cxx:189
void SetQOverflow(Bool_t qOvfl)
Definition: Mdc2DWire.cxx:513
virtual void CloseInfo()
Definition: Mdc2DWire.cxx:195
virtual void SetHighlighted(bool status=true)
Definition: Mdc2DWire.h:32
virtual bool IsFired()
Definition: Mdc2DWire.h:35
virtual char * GetObjectInfo(Int_t px, Int_t py) const
Definition: Mdc2DWire.cxx:414
virtual bool IsHighlighted()
Definition: Mdc2DWire.h:34
virtual bool HasZRSection()
Definition: Mdc2DWire.cxx:423
void SetTime(Double_t time)
Definition: Mdc2DWire.cxx:499
void SetColorfulWire(Bool_t colorfulWire, Bool_t subEvTime)
Definition: Mdc2DWire.cxx:538
Double_t Range360(Double_t input)
Definition: Mdc2DWire.cxx:479
void SetEvTime(Double_t time)
Definition: Mdc2DWire.cxx:520
virtual void Paint(Option_t *option="")
Definition: Mdc2DWire.cxx:296
virtual void Init()
Definition: Mdc2DWire.cxx:137
virtual void SetStyle()
Definition: Mdc2DWire.cxx:147
void SetTimeChannel(UInt_t tc)
Definition: Mdc2DWire.cxx:527
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Definition: Mdc2DWire.cxx:209
virtual void Draw(Option_t *option="")
Definition: Mdc2DWire.cxx:285
void SetCharge(Double_t charge)
Definition: Mdc2DWire.cxx:506
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Definition: Mdc2DWire.cxx:233
c1_1 Draw()