Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.Views/3.3/Container3DView.xaml.cs @ 13576

Last change on this file since 13576 was 13576, checked in by gkronber, 8 years ago

#1966: folder reorganization (only 4 classes left in .Views plugin)

File size: 9.9 KB
Line 
1using System;
2using System.Linq;
3using System.Windows;
4using System.Windows.Controls;
5using System.Windows.Input;
6using System.Windows.Media.Media3D;
7using HeuristicLab.Encodings.PackingEncoding.PackingPlan;
8using HeuristicLab.Problems.BinPacking.Dimensions;
9using HeuristicLab.Problems.BinPacking.PackingBin;
10using HeuristicLab.Problems.BinPacking.PackingItem;
11
12namespace HeuristicLab.Problems.BinPacking.Views {
13  public partial class Container3DView : UserControl {
14    private Point startPos;
15    private bool mouseDown = false;
16    private double startAngleX;
17    private double startAngleY;
18    private int selectedItemKey;
19
20    private BinPacking<ThreeDimensionalPacking, CuboidPackingBin, CuboidPackingItem> packing;
21    public BinPacking<ThreeDimensionalPacking, CuboidPackingBin, CuboidPackingItem> Packing {
22      get { return packing; }
23      set {
24        if (packing != value) {
25          this.packing = value;
26          ClearSelection(); // also updates visualization
27        }
28      }
29    }
30
31    public Container3DView() {
32      InitializeComponent();
33      camMain.Position = new Point3D(0.5, 2, 2); // for design time we use a different camera position
34      Clear();
35    }
36
37
38    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) {
39      base.OnRenderSizeChanged(sizeInfo);
40      var s = Math.Min(sizeInfo.NewSize.Height, sizeInfo.NewSize.Width);
41      var mySize = new Size(s, s);
42      viewport3D1.RenderSize = mySize;
43    }
44
45    public void SelectItem(int itemKey) {
46      // selection of an item should make all other items semi-transparent
47      selectedItemKey = itemKey;
48      UpdateVisualization();
49    }
50    public void ClearSelection() {
51      // remove all transparency
52      selectedItemKey = -1;
53      UpdateVisualization();
54    }
55
56    private void UpdateVisualization() {
57      Clear();
58      if (packing == null) return; // nothing to display
59
60      // draw all items
61      // order by Z position to reduce artifacts (because of transparent objects)
62      // TODO: improve code to reduce artifacts
63      //  - from triangle definitions and lighting
64      //  - from rotation and Z-ordering
65
66      foreach (var item in packing.ItemMeasures.OrderBy(i => packing.ItemPositions[i.Key].Z)) {
67        var position = packing.ItemPositions[item.Key];
68
69        var w = position.Rotated ? item.Value.Depth : item.Value.Width;
70        var h = item.Value.Height;
71        var d = position.Rotated ? item.Value.Width : item.Value.Depth;
72
73        // ignore the item.Material
74
75        // if nothing is selected then draw all cubes opaque
76        // otherwise draw only the selected cube opaque and all others transparent
77        if (selectedItemKey < 0 || selectedItemKey == item.Key) {
78          AddCube(meshMain, position.X, position.Y, position.Z, w, h, d);
79        } else {
80          AddCube(meshTransparent, position.X, position.Y, position.Z, w, h, d, addInsideTriangles: true);
81        }
82      }
83
84      var container = packing.BinMeasures;
85      // draw a transparent container
86      AddCube(meshTransparent, container.Origin.X, container.Origin.Y, container.Origin.Z, container.Width, container.Height, container.Depth, addInsideTriangles: true);
87
88      // TODO: support cuboids with different side lengths
89      // apply scaling so that the container fits into the unit cube (necessary for the transformations)
90      scale.ScaleX = 1.0 / (container.Width);
91      scale.ScaleY = 1.0 / (container.Height);
92      scale.ScaleZ = 1.0 / (container.Depth);
93    }
94
95
96    private void Clear() {
97      meshInsides.Positions.Clear();
98      meshInsides.TriangleIndices.Clear();
99
100      meshMain.Positions.Clear();
101      meshMain.TriangleIndices.Clear();
102
103      meshTransparent.Positions.Clear();
104      meshTransparent.TriangleIndices.Clear();
105
106      mouseDown = false;
107      startAngleX = 0;
108      startAngleY = 0;
109    }
110
111    private void Container3DView_MouseMove(object sender, MouseEventArgs e) {
112      if (!mouseDown) return;
113      var pos = e.GetPosition((IInputElement)this);
114      rotateX.Angle = startAngleX + (pos.X - startPos.X) / 4;
115      rotateY.Angle = startAngleY + (pos.Y - startPos.Y) / 4;
116    }
117
118    private void Container3DView_MouseDown(object sender, MouseButtonEventArgs e) {
119      startAngleX = rotateX.Angle;
120      startAngleY = rotateY.Angle;
121      this.startPos = e.GetPosition((IInputElement)this);
122      this.mouseDown = true;
123    }
124
125    private void Container3DView_MouseUp(object sender, MouseButtonEventArgs e) {
126      mouseDown = false;
127    }
128
129    private void Container3DView_OnMouseWheel(object sender, MouseWheelEventArgs e) {
130      if (e.Delta > 0) {
131        scaleZoom.ScaleX *= 1.1;
132        scaleZoom.ScaleY *= 1.1;
133        scaleZoom.ScaleZ *= 1.1;
134      } else if (e.Delta < 0) {
135        scaleZoom.ScaleX /= 1.1;
136        scaleZoom.ScaleY /= 1.1;
137        scaleZoom.ScaleZ /= 1.1;
138      }
139    }
140
141
142    #region helper for cubes
143
144    private void AddCube(MeshGeometry3D mesh, int x, int y, int z, int width, int height, int depth, bool addInsideTriangles = false) {
145      AddOutsideTriangles(mesh, AddPoints(mesh, x, y, z, width, height, depth));
146      if (addInsideTriangles) AddInsideTriangles(meshInsides, AddPoints(meshInsides, x, y, z, width, height, depth));
147    }
148
149    private void AddOutsideTriangles(MeshGeometry3D mesh, int[] pointIdx) {
150      // point indices counter-clockwise
151      // back side
152      mesh.TriangleIndices.Add(pointIdx[0]);
153      mesh.TriangleIndices.Add(pointIdx[2]);
154      mesh.TriangleIndices.Add(pointIdx[1]);
155
156      mesh.TriangleIndices.Add(pointIdx[0]);
157      mesh.TriangleIndices.Add(pointIdx[3]);
158      mesh.TriangleIndices.Add(pointIdx[2]);
159
160      // bottom side
161      mesh.TriangleIndices.Add(pointIdx[5]);
162      mesh.TriangleIndices.Add(pointIdx[4]);
163      mesh.TriangleIndices.Add(pointIdx[0]);
164
165      mesh.TriangleIndices.Add(pointIdx[5]);
166      mesh.TriangleIndices.Add(pointIdx[0]);
167      mesh.TriangleIndices.Add(pointIdx[1]);
168
169      // right side
170      mesh.TriangleIndices.Add(pointIdx[2]);
171      mesh.TriangleIndices.Add(pointIdx[6]);
172      mesh.TriangleIndices.Add(pointIdx[5]);
173
174      mesh.TriangleIndices.Add(pointIdx[1]);
175      mesh.TriangleIndices.Add(pointIdx[2]);
176      mesh.TriangleIndices.Add(pointIdx[5]);
177
178      // left side
179      mesh.TriangleIndices.Add(pointIdx[7]);
180      mesh.TriangleIndices.Add(pointIdx[3]);
181      mesh.TriangleIndices.Add(pointIdx[4]);
182
183      mesh.TriangleIndices.Add(pointIdx[4]);
184      mesh.TriangleIndices.Add(pointIdx[3]);
185      mesh.TriangleIndices.Add(pointIdx[0]);
186
187      // top side
188      mesh.TriangleIndices.Add(pointIdx[3]);
189      mesh.TriangleIndices.Add(pointIdx[7]);
190      mesh.TriangleIndices.Add(pointIdx[6]);
191
192      mesh.TriangleIndices.Add(pointIdx[3]);
193      mesh.TriangleIndices.Add(pointIdx[6]);
194      mesh.TriangleIndices.Add(pointIdx[2]);
195
196      // front side
197      mesh.TriangleIndices.Add(pointIdx[6]);
198      mesh.TriangleIndices.Add(pointIdx[7]);
199      mesh.TriangleIndices.Add(pointIdx[4]);
200
201      mesh.TriangleIndices.Add(pointIdx[6]);
202      mesh.TriangleIndices.Add(pointIdx[4]);
203      mesh.TriangleIndices.Add(pointIdx[5]);
204    }
205
206    private void AddInsideTriangles(MeshGeometry3D mesh, int[] pointIdx) {
207      // for each cube we also draw the triangles facing inside because they are visible when a cube is transparent
208      // point indices clockwise
209
210      // back side
211      mesh.TriangleIndices.Add(pointIdx[1]);
212      mesh.TriangleIndices.Add(pointIdx[2]);
213      mesh.TriangleIndices.Add(pointIdx[0]);
214
215      mesh.TriangleIndices.Add(pointIdx[2]);
216      mesh.TriangleIndices.Add(pointIdx[3]);
217      mesh.TriangleIndices.Add(pointIdx[0]);
218
219      // bottom side
220      mesh.TriangleIndices.Add(pointIdx[0]);
221      mesh.TriangleIndices.Add(pointIdx[4]);
222      mesh.TriangleIndices.Add(pointIdx[5]);
223
224      mesh.TriangleIndices.Add(pointIdx[1]);
225      mesh.TriangleIndices.Add(pointIdx[0]);
226      mesh.TriangleIndices.Add(pointIdx[5]);
227
228      // right side
229      mesh.TriangleIndices.Add(pointIdx[5]);
230      mesh.TriangleIndices.Add(pointIdx[6]);
231      mesh.TriangleIndices.Add(pointIdx[2]);
232
233      mesh.TriangleIndices.Add(pointIdx[5]);
234      mesh.TriangleIndices.Add(pointIdx[2]);
235      mesh.TriangleIndices.Add(pointIdx[1]);
236
237      // left side
238      mesh.TriangleIndices.Add(pointIdx[4]);
239      mesh.TriangleIndices.Add(pointIdx[3]);
240      mesh.TriangleIndices.Add(pointIdx[7]);
241
242      mesh.TriangleIndices.Add(pointIdx[0]);
243      mesh.TriangleIndices.Add(pointIdx[3]);
244      mesh.TriangleIndices.Add(pointIdx[4]);
245
246      // top side
247      mesh.TriangleIndices.Add(pointIdx[6]);
248      mesh.TriangleIndices.Add(pointIdx[7]);
249      mesh.TriangleIndices.Add(pointIdx[3]);
250
251      mesh.TriangleIndices.Add(pointIdx[2]);
252      mesh.TriangleIndices.Add(pointIdx[6]);
253      mesh.TriangleIndices.Add(pointIdx[3]);
254
255      // front side
256      mesh.TriangleIndices.Add(pointIdx[4]);
257      mesh.TriangleIndices.Add(pointIdx[7]);
258      mesh.TriangleIndices.Add(pointIdx[6]);
259
260      mesh.TriangleIndices.Add(pointIdx[5]);
261      mesh.TriangleIndices.Add(pointIdx[4]);
262      mesh.TriangleIndices.Add(pointIdx[6]);
263    }
264
265    private int[] AddPoints(MeshGeometry3D mesh, int x, int y, int z, int w, int h, int d) {
266      // ground
267      mesh.Positions.Add(new Point3D(x, y, z));
268      mesh.Positions.Add(new Point3D(x + w, y, z));
269      mesh.Positions.Add(new Point3D(x + w, y + h, z));
270      mesh.Positions.Add(new Point3D(x, y + h, z));
271      // top
272      mesh.Positions.Add(new Point3D(x, y, z + d));
273      mesh.Positions.Add(new Point3D(x + w, y, z + d));
274      mesh.Positions.Add(new Point3D(x + w, y + h, z + d));
275      mesh.Positions.Add(new Point3D(x, y + h, z + d));
276
277      return Enumerable.Range(mesh.Positions.Count - 8, 8).ToArray();
278    }
279    #endregion
280
281    private void Container3DView_OnMouseEnter(object sender, MouseEventArgs e) {
282      Focus(); // for mouse wheel events
283    }
284  }
285}
Note: See TracBrowser for help on using the repository browser.