Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1966: removed types for *PackingBin because PackingBins and PackingShapes have the same capabilities

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