Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1966: unified namespaces

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