VIS2 SS2013 CVD DVR
 All Classes Namespaces Functions Enumerations Properties
Transferfunction.cs
1 #region Using Statement
2 using System;
3 using System.Drawing;
4 using System.Windows.Forms;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Text;
8 using Microsoft.Xna.Framework;
9 using Microsoft.Xna.Framework.Content;
10 using Microsoft.Xna.Framework.Graphics;
11 #endregion
12 
13 //use XNA defionitions for color and rectangle, System.Drawing for point
14 using Color = Microsoft.Xna.Framework.Color;
15 using Rectangle = Microsoft.Xna.Framework.Rectangle;
16 using Point = System.Drawing.Point;
17 
18 namespace visLU.Gui
19 {
24  {
25  #region Variables
26 
27  BasicEffect effect;
28  SortedDictionary<int, TransferControlPoint> controlPointValues; // key -> iso value = 0 - 255, color -> 0.0f to 1.0f, alpha -> 0.0f to 1.0f
29  SortedDictionary<float, float> densityIsoValues;
30  bool enableTransferFunction;
31 
32  VertexPositionColor[] densityPoints; //array to draw the density function for the current dataset(draw -> x == isovalue, y == density)
33  VertexPositionColor[] controlPoints; //array to connect the control points(->draw)
34 
35  int scaleX = 255;
36  int scaleY= 255;
37  int minWidth = 256;
38  int minHeight = 150;
39  bool drawDensityFunction; //im gui einbinden TODO
40  int cpTexWidth = 9;
41  int cpTexHeight = 9;
42 
43 
44  SpriteBatch spriteBatch;
45  ContentManager content;
46  Texture2D transparentPattern;
47  Texture2D tfBackground;
48  Texture2D controlPointTex;
49  Color[] tfBackgroundColor;
50 
51  //state variables
52  bool updateIsoValues; //set true if new dataset has been loaded
53  bool getControlPoints; //set true to load initial control points(new dataset was loaded) or xml def
54  bool setControlPoints; //set true when new cp was added in the tf control panel
55 
56  bool sizeChanged;
57  Size defaultSize = new Size(256,256);
58  Size lastSize;
59 
60  #endregion
61 
62  #region Properties
63  public bool EnableTransferFunction
64  {
65  set { enableTransferFunction = value; }
66  }
67  public bool DensityFunction
68  {
69  set { drawDensityFunction = value; }
70  }
71 
72  public bool UpdateIsoValues
73  {
74  set { updateIsoValues = value; }
75  }
76 
77  public bool GetControlPoints
78  {
79  set { getControlPoints = value; }
80  }
81 
82  public bool SetControlPoints
83  {
84  set { setControlPoints = value; }
85  get { return setControlPoints; }
86  }
87  #endregion
88 
89  protected override void Initialize()
90  {
91 
92  //this.MinimumSize = new System.Drawing.Size(minWidth, minHeight);
93  lastSize = this.Size;
94 
95  spriteBatch = Services.GetService(typeof(SpriteBatch)) as SpriteBatch;
96  content = Services.GetService(typeof(ContentManager)) as ContentManager;
97 
98  updateIsoValues = false; //set true if new dataset has been loaded
99  getControlPoints = false; //set true to load initial control points(new dataset was loaded) or xml def
100  setControlPoints = false; //set true when new cp was added in the tf control panel
101  sizeChanged = false;
102 
103  controlPointValues = new SortedDictionary<int, TransferControlPoint>();
104  getControlPointsData();
105  setCpData();
106  tfBackgroundColor = new Color[256*256];
107 
108  densityIsoValues = new SortedDictionary<float, float>();
109 
110  enableTransferFunction = GameProperties.Instance.enableTransferFunction;
111  drawDensityFunction = (GameProperties.Instance.showDensityValue && GameProperties.Instance.engineState.loadData);
112  }
113 
114  protected override void LoadContent()
115  {
116 
117  if (spriteBatch == null)
118  {
119  //throw new InvalidOperationException("SpriteBatch Service not found");
120  spriteBatch = new SpriteBatch(GraphicsDevice);
121  Services.AddService<SpriteBatch>(spriteBatch);
122  }
123 
124  if (content == null)
125  {
126  //throw new InvalidOperationException("Content Manager Service not found.");
127  content = new ContentManager(Services, "Content");
128  Services.AddService<ContentManager>(content);
129  }
130 
131  transparentPattern = content.Load<Texture2D>("Texture\\transparent_pattern");
132  tfBackground = new Texture2D(GraphicsDevice, 256, 256, false, SurfaceFormat.Color);
133  interpolateColor();
134  tfBackground.SetData(tfBackgroundColor);
135 
136  controlPointTex = content.Load<Texture2D>("Texture\\circle");
137 
138  //create effect
139  effect = new BasicEffect(GraphicsDevice);
140  effect.VertexColorEnabled = true;
141  }
142 
147  protected override void Update()
148  {
149  Console.WriteLine("Transferfunction Update Call");
150 
151  if (!enableTransferFunction) return;
152 
153  #region update iso values
154  //if new dataset has been loaded -> update the density function
155  if (updateIsoValues)
156  {
157  updateIsoValuesData();
158  setDensityPoints();
159  updateIsoValues = false;
160  }
161 
162  #endregion
163 
164  #region update control points
165  //update if
166  //1. new dataset has been loaded -> initial points
167  //2. xml definition has been loaded -> read new control points from the game properties
168  if (getControlPoints)
169  {
170  getControlPointsData();
171  setCpData();
172  interpolateColor();
173  tfBackground.SetData(tfBackgroundColor); //do i need to do this???
174  getControlPoints = false;
175  }
176 
177  //3. new cp has been added
178  if (setControlPoints)
179  {
180  setCpData();
181  interpolateColor();
182  tfBackground.SetData(tfBackgroundColor); //do i need to do this???
183  setControlPoints = false;
184  }
185  #endregion
186 
187  #region control size changed
188  //scale if size has been changed
189  //scale after all updates are done
190  if (sizeChanged)
191  {
192  if (!getControlPoints && !setControlPoints)
193  {
194  setCpData();
195  }
196  if (drawDensityFunction)
197  setDensityPoints();
198 
199  sizeChanged = false;
200  }
201  #endregion
202 
203  }
204 
208  protected override void Draw()
209  {
210  Console.WriteLine("Transferfunction Draw Call");
211 
212  if (!enableTransferFunction)
213  {
214  GraphicsDevice.Clear(Color.CornflowerBlue);
215  #region draw transparent pattern texture as background
216  spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
217  spriteBatch.Draw(transparentPattern, new Rectangle(0, 0, Width, Height), Color.White);
218  spriteBatch.End();
219  #endregion
220  return;
221  }
222 
223  GraphicsDevice.Clear(Color.CornflowerBlue);
224  effect.World = Matrix.Identity;
225  effect.View = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up);
226  effect.Projection = Matrix.CreateOrthographicOffCenter(0, (float)GraphicsDevice.Viewport.Width, (float)GraphicsDevice.Viewport.Height, 0, 1.0f, 1000.0f);
227 
228 
229  #region draw background
230  spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
231  spriteBatch.Draw(transparentPattern, new Rectangle(0, 0, Width, Height), Color.White);
232  spriteBatch.Draw(tfBackground, new Rectangle(0, 0, Width, Height), Color.White);
233  spriteBatch.End();
234  #endregion
235 
236 
237  #region draw density function
238  if (drawDensityFunction)
239  {
240  GraphicsDevice.RasterizerState = RasterizerState.CullNone;
241  effect.CurrentTechnique.Passes[0].Apply();
242  GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineStrip,
243  densityPoints, 0, (densityPoints.Count()-1));
244  }
245  #endregion
246 
247  //draw control points
248  #region draw control points
249 
250  //connect the control points
251  GraphicsDevice.RasterizerState = RasterizerState.CullNone;
252  effect.CurrentTechnique.Passes[0].Apply();
253  GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineStrip,
254  controlPoints, 0, (controlPoints.Count() - 1));
255 
256  spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
257  foreach (KeyValuePair<int,TransferControlPoint> p in controlPointValues)
258  {
259 
260  float scaleX_ = ((float)(this.Width - 1) / (float)scaleX);
261  float scaleY_ = ((float)(this.Height - 1) / (float)scaleY);
262  //int x = (int)((p.Value.isoValue - (int)(cpTexWidth * 0.5f))*scaleX_);
263  //int y = (int)((150 - (int)(cpTexHeight * 0.5f))*scaleY_);
264  int x = (int)(p.Value.isoValue * scaleX_ - (int)(cpTexWidth * 0.5f));
265  int y = (int)((this.Height - 1 - p.Value.color.W * 255.0f * scaleY_) - (int)(cpTexHeight * 0.5f));
266  Color color = new Color(p.Value.color);
267  //draw with control point color and conect the control points
268  spriteBatch.Draw(controlPointTex, new Rectangle(x, y, cpTexHeight, cpTexWidth), color);
269  }
270  spriteBatch.End();
271  #endregion
272  }
273 
274  #region Help Functions
275 
279  private void getControlPointsData()
280  {
281 
282  //load control points from a xml file defintion
283  if (GameProperties.Instance.colorControlPoints != null && GameProperties.Instance.colorControlPoints.Count() > 0)
284  {
285  controlPointValues.Clear();
286  for (int i = 0; i < GameProperties.Instance.colorControlPoints.Count(); i++)
287  {
288  int cpValue = GameProperties.Instance.colorControlPoints[i].isoValue;
289  TransferControlPoint cpNext = GameProperties.Instance.colorControlPoints[i];
290  cpNext.color.W = GameProperties.Instance.alphaControlPoints[i].color.W;
291  controlPointValues.Add(cpValue, cpNext);
292  }
293 
294  }
295  else //get default control points from the game properties instance, when new dataset was loaded
296  {
297  if (controlPointValues.Count > 0) controlPointValues.Clear();
298  //initial control points-> need this for the texture if no control points are set!
299 
300  #region old version -> delete after test
301  /*controlPointValues.Add(0, new TransferControlPoint(0.0f, 0.0f, 0.0f, 0));//bottom left
302  controlPointValues.Add(255, new TransferControlPoint(0.0f, 0.0f, 0.0f, 255));//bottom right
303 
304  #region test
305  controlPointValues.Add(50, new TransferControlPoint(1.0f, 0.0f, 0.0f, 50));
306  controlPointValues.Add(150, new TransferControlPoint(0.0f, 1.0f, 0.0f, 150));
307  controlPointValues.Add(250, new TransferControlPoint(0.0f, 0.0f, 1.0f, 250));
308  #endregion
309 
310  //set points in the game properties -> better way to do this or some gut default points
311  foreach (KeyValuePair<int, TransferControlPoint> cp in controlPointValues)
312  {
313 
314  GameProperties.Instance.colorControlPoints.Add(new TransferControlPoint(cp.Value.color.X, cp.Value.color.Y, cp.Value.color.Z, cp.Value.isoValue));
315  GameProperties.Instance.alphaControlPoints.Add(new TransferControlPoint(cp.Value.color.W, cp.Value.isoValue));
316  }*/
317  #endregion
318 
319  }
320  }
321 
322 
323 
329  void setCpData()
330  {
331  if (controlPointValues == null || controlPointValues.Count == 0) return;
332 
333  controlPoints = new VertexPositionColor[controlPointValues.Count];
334  float scaleX_ = ((float)(this.Width - 1) / (float)scaleX);
335  float scaleY_ = ((float)(this.Height - 1) / (float)scaleY);
336  int i = 0;
337  foreach (KeyValuePair<int, TransferControlPoint> cp in controlPointValues)
338  {
339  //(int) alpha * 255 ?
340  Color color = new Color(cp.Value.color);
341  color.A = 255;
342  controlPoints[i] = new VertexPositionColor(
343  new Vector3((cp.Value.isoValue * scaleX_), (this.Height - 1) - ((cp.Value.color.W * 255.0f) * scaleY_), 0),
344  color);
345  i++;
346  }
347  //OLD STUFF -> DELETE
348  /*for (int i = 0; i < controlPointValues.Count; i++)
349  {
350  controlPoints[i] = new VertexPositionColor(
351  new Vector3((controlPointValues[i].isoValue * scaleX_), ((this.Height - 1 - controlPointValues[i].color.W)* scaleY_), 0),
352  new Color(controlPointValues[i].color));
353  }*/
354  }
355 
359  void interpolateColor()
360  {
361 
362  #region current version
363 
364  List<TransferControlPoint> cpList;
365 
366  if (GameProperties.Instance.colorControlPoints != null && GameProperties.Instance.colorControlPoints.Count > 0)
367  {
368  cpList = new List<TransferControlPoint>(GameProperties.Instance.colorControlPoints);
369  //cpList = GameProperties.Instance.colorControlPoints;
370  }
371  else
372  {
373  cpList = new List<TransferControlPoint>();
374  foreach(KeyValuePair<int, TransferControlPoint> cp in controlPointValues)
375  {
376 
377  cpList.Add(cp.Value);
378  }
379 
380  }
381 
382  cpList.Sort(delegate(TransferControlPoint p1,
383  TransferControlPoint p2) { return p1.isoValue.CompareTo(p2.isoValue); });
384 
385  float amount = 0.0f;
386 
387 
388  for (int k = 0; k < 256; k++)
389  {
390  byte alpha = (byte)(255 - k); //alpha for each row
391 
392  for (int i = 0; i < cpList[0].isoValue; i++)
393  {
394  tfBackgroundColor[i + 256 * k] = Color.Black;
395  tfBackgroundColor[i + 256 * k].A = alpha;
396 
397  }
398 
399  for (int j = 0; j < cpList.Count - 1; j++)
400  {
401  for (int i = cpList[j].isoValue; i <= cpList[j + 1].isoValue; i++)
402  {
403  amount = (((float)i - cpList[j].isoValue) /
404  (cpList[j + 1].isoValue - cpList[j].isoValue));
405  tfBackgroundColor[i + 256 * k] = Color.Lerp(new Color(cpList[j].color),
406  new Color(cpList[j + 1].color), amount);
407  tfBackgroundColor[i + 256 * k].A = alpha;
408  }
409  }
410 
411  // after last ControlPoint: fill with black and alpha
412  for (int i = cpList[cpList.Count - 1].isoValue + 1; i < 256; i++)
413  {
414  tfBackgroundColor[i + 256 * k] = Color.Black;
415  tfBackgroundColor[i + 256 * k].A = alpha;
416  }
417 
418  }//end for k
419  #endregion
420 
421  #region old version 2
422 
423  /*Color[] colorArray = new Color[256];
424  float amount = 0.0f;
425 
426  // before first ControlPoint: fill with black and alpha 0.0f
427  for (int i = 0; i < colorControlPoints[0].isoValue; i++)
428  {
429  colorArray[i] = Color.Black;
430 
431  }
432 
433  for (int j = 0; j < colorControlPoints.Count - 1; j++)
434  {
435  for (int i = colorControlPoints[j].isoValue; i <= colorControlPoints[j + 1].isoValue; i++)
436  {
437  amount = (((float)i - colorControlPoints[j].isoValue) /
438  (colorControlPoints[j + 1].isoValue - colorControlPoints[j].isoValue));
439  colorArray[i] = Color.Lerp(new Color(colorControlPoints[j].color),
440  new Color(colorControlPoints[j + 1].color), amount);
441  }
442  }
443 
444  // after last ControlPoint: fill with black and alpha
445  for (int i = colorControlPoints[colorControlPoints.Count - 1].isoValue + 1; i < 256; i++)
446  {
447  colorArray[i] = Color.Black;
448  }
449 
450  //init texture to draw background
451  for (int i = 0; i < 256; i++)
452  {
453  for (int j = 0; j < colorArray.Count(); j++)
454  {
455  byte alpha = (byte)(255-i);
456  tfBackgroundColor[j + 256 * i] = colorArray[j];
457  tfBackgroundColor[j + 256 * i].A = alpha;
458 
459  }
460 
461  }*/
462 
463  #endregion
464 
465  }
466 
467 
468 
473  private void updateIsoValuesData()
474  {
475  if (GameProperties.Instance.distinctDensityValues != null && GameProperties.Instance.distinctDensityValues.Length > 0)
476  {
477  densityIsoValues.Clear(); ; //key->iso value, value -> log densitiy
478  //float maxDensity = (float)Math.Log10(GameProperties.Instance.countDensityValues.Max() - GameProperties.Instance.countDensityValues.Min()); //TODO debug density scale
479  float maxDensity = (float)Math.Log10(GameProperties.Instance.countDensityValues.Max() - GameProperties.Instance.countDensityValues.Min());
480  for (int i = 0; i < GameProperties.Instance.distinctDensityValues.Length; i++)
481  {
482  densityIsoValues.Add(GameProperties.Instance.distinctDensityValues[i], (float)Math.Log10(GameProperties.Instance.countDensityValues[i])/maxDensity);
483  }
484  }
485 
486  }
487 
492  void setDensityPoints()
493  {
494  if (densityIsoValues == null || densityIsoValues.Count == 0) return;
495  densityPoints = new VertexPositionColor[densityIsoValues.Count];
496  int i = 0;
497  float scaleX_ = ((float)(this.Width - 1) / (float)scaleX);
498  float scaleY_ = ((float)(this.Height - 1) / (float)scaleY);
499 
500  foreach (KeyValuePair<float, float> isoValue in densityIsoValues)
501  {
502  densityPoints[i] = new VertexPositionColor(new Vector3(isoValue.Key * scaleX_, ((this.Height - 1) - (isoValue.Value*255.0f)*scaleY_), 0), Color.Black);
503  i++;
504  }
505  }
506 
507  #endregion
508 
509  #region Control Points Helper Functions
510  public void setControlPoint(Point position, System.Drawing.Color color)
517  {
518 
519  float r = (float)(color.R / 255.0f);
520  float g = (float)(color.G / 255.0f);
521  float b = (float)(color.B / 255.0f);
522  float a = (float)((255 - position.Y) / 255.0f); //check if color correct
523 
524  int key = getControlPointKey(position);
525 
526  if (key == -1) //add new control point
527  {
528  float scaleX_ = ((float)(this.Width - 1) / (float)scaleX);
529  int posX = (int)(position.X / scaleX_);
530  GameProperties.Instance.colorControlPoints.Add(new TransferControlPoint(r, g, b, posX));
531  GameProperties.Instance.alphaControlPoints.Add(new TransferControlPoint(a, posX));
532  TransferControlPoint cpNew = new TransferControlPoint(r, g, b, posX);
533  cpNew.color.W = a;
534  controlPointValues.Add(position.X, cpNew);
535 
536  }
537  else //edit color for the current one
538  {
539  controlPointValues[key].color.X = r;
540  controlPointValues[key].color.Y = g;
541  controlPointValues[key].color.Z = b;
542  controlPointValues[key].color.W = a;
543 
544  for (int i = 0; i < GameProperties.Instance.colorControlPoints.Count(); i++)
545  {
546  if (GameProperties.Instance.colorControlPoints[i].isoValue == key
547  && GameProperties.Instance.alphaControlPoints[i].isoValue == key)
548  {
549  GameProperties.Instance.colorControlPoints[i].color.X = r;
550  GameProperties.Instance.colorControlPoints[i].color.Y = g;
551  GameProperties.Instance.colorControlPoints[i].color.Z = b;
552  GameProperties.Instance.alphaControlPoints[i].color.W = a;
553  i = GameProperties.Instance.colorControlPoints.Count();
554  }
555  }
556 
557 
558  }
559  //debug
560  //Console.WriteLine("color piker value:" + "{" + r + ", " + g + ", " + b + "; " + a );
561 
562  }
563 
569  public bool changeControlPoint(Point oldPosition, Point newPosition)
570  {
571  int key = getControlPointKey(oldPosition); //old mouse position
572  if (key != -1)
573  {
574  oldPosition.X = key;
575 
576  //normalize position
577  float scaleX_ = ((float)(this.Width - 1) / (float)scaleX);
578  float scaleY_ = ((float)(this.Height - 1) / (float)scaleY);
579 
580  //int oldIsoValue = (int)(oldPosition.X / scaleX_);
581  int newIsoValue = (int)((newPosition.X) / scaleX_);
582  float newAlphaValue = (float)((this.Height - 1 - newPosition.Y) / scaleY_);
583  newAlphaValue /= 255.0f;
584  //Console.WriteLine("new alpha = " + newAlpaValue);
585 
586  if (newIsoValue == oldPosition.X)//only alpha changed
587  {
588  controlPointValues[newIsoValue].color.W = newAlphaValue;
589  }
590  else
591  {
592  TransferControlPoint cp = controlPointValues[oldPosition.X];
593  cp.isoValue = newIsoValue;
594  cp.color.W = newAlphaValue;
595  controlPointValues.Remove(oldPosition.X);
596  if (controlPointValues.ContainsKey(newIsoValue)) //cp for this iso value already exists so override it
597  controlPointValues[newIsoValue] = cp;
598  else controlPointValues.Add(newIsoValue, cp);
599 
600  }
601 
602  changeControlPoints();
603  return true;
604 
605  }
606  return false;
607  }
608 
613  public bool removeControlPoint(Point cpPosition)
614  {
615  int key = getControlPointKey(cpPosition); //old mouse position
616  if (key != -1)
617  {
618  if (controlPointValues.Remove(key))
619  {
620  for (int i = 0; i < GameProperties.Instance.colorControlPoints.Count(); i++)
621  {
622  if (GameProperties.Instance.colorControlPoints[i].isoValue == key
623  && GameProperties.Instance.alphaControlPoints[i].isoValue == key)
624  {
625  GameProperties.Instance.colorControlPoints.RemoveAt(i);
626  GameProperties.Instance.alphaControlPoints.RemoveAt(i);
627  break;
628  }
629  }
630  return true;
631  }
632 
633  }
634 
635  return false;
636  }
637 
641  void changeControlPoints()
642  {
643  GameProperties.Instance.colorControlPoints.Clear();
644  GameProperties.Instance.alphaControlPoints.Clear();
645 
646  foreach (KeyValuePair<int, TransferControlPoint> cp in this.controlPointValues)
647  {
648  GameProperties.Instance.colorControlPoints.Add(new TransferControlPoint(cp.Value.color.X, cp.Value.color.Y, cp.Value.color.Z, cp.Value.isoValue));
649  GameProperties.Instance.alphaControlPoints.Add(new TransferControlPoint(cp.Value.color.W, cp.Value.isoValue));
650 
651  }
652 
653  }
659  int getControlPointKey(Point mousePos)
660  {
661  //normalize position
662  float scaleX_ = ((float)(this.Width - 1) / (float)scaleX);
663  float scaleY_ = ((float)(this.Height - 1) / (float)scaleY);
664 
665  mousePos.X = (int)(mousePos.X / scaleX_);
666  mousePos.Y = (int)((this.Height - 1 - mousePos.Y) / scaleY_);
667 
668  if (controlPointValues.ContainsKey(mousePos.X)) return mousePos.X;
669 
670  else
671  {
672 
673  foreach (int key in controlPointValues.Keys)
674  {
675  if (mousePos.X >= (key - (cpTexWidth / 2)) &&
676  mousePos.X <= (key + (cpTexWidth / 2)))
677  {
678  return key;
679  }
680  }
681  }
682 
683  return -1;
684  }
685  #endregion
686 
687  #region Control Properties Events
688  protected override void OnSizeChanged(EventArgs e)
689  {
690  //if new size == last size then no update call
691  if (this.Size != lastSize)
692  {
693  //Console.WriteLine("Size:" + Size);
694  lastSize = this.Size;
695  sizeChanged = true;
696 
697  }
698  base.OnSizeChanged(e);
699 
700  }
701 
702  /*protected override void OnAutoSizeChanged(EventArgs e)
703  {
704  //if new size == last size then no update call
705  if (this.Size != lastSize)
706  {
707  //Console.WriteLine("Size:" + Size);
708  lastSize = this.Size;
709  sizeChanged = true;
710 
711  }
712  base.OnAutoSizeChanged(e);
713 
714  }*/
715  #endregion
716  }
717 }