Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1966: refactoring

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