VCG Library
space_rasterized_packer.cpp
1 /****************************************************************************
2 * VCGLib o o *
3 * Visual and Computer Graphics Library o o *
4 * _ O _ *
5 * Copyright(C) 2004-2019 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23 #include <iostream>
24 #include <vector>
25 #include <cassert>
26 #include <string>
27 
28 #include <vcg/space/point2.h>
29 #include <vcg/space/point3.h>
30 #include <vcg/complex/algorithms/outline_support.h>
31 #include <wrap/qt/outline2_rasterizer.h>
32 #include <vcg/space/rasterized_outline2_packer.h>
33 
34 #include <wrap/qt/Outline2ToQImage.h>
35 
36 // This sample shows how to pack a sequence of outlines at the given scale into
37 // a number of containers not known in advance using the PackBestEffort()
38 // function
39 
40 typedef std::vector<vcg::Point2f> Outline2f;
41 typedef vcg::RasterizedOutline2Packer<float,QtOutline2Rasterizer> RasterizedPacker;
42 typedef RasterizedPacker::Parameters PackingParams;
43 
44 
45 void FillOutlineVec(std::vector<Outline2f>& outlines)
46 {
47  vcg::tri::OutlineUtil<float>::BuildRandomOutlineVec(30, outlines);
48  for (auto& outline : outlines)
49  for (auto& p : outline)
50  p *= 200.0;
51 }
52 
53 int main(int argc, char **argv)
54 {
55  // the vector of outlines to pack
56  std::vector<Outline2f> outlines;
57  FillOutlineVec(outlines);
58 
59  // containerIndices maps each outline index to the container in which is packed
60  std::vector<int> containerIndices(outlines.size(), -1); // -1 means not packed to any container
61 
62  // packingTransforms maps each outline index to its transform */
63  std::vector<vcg::Similarity2f> packingTransforms(outlines.size(), vcg::Similarity2f{});
64 
65  /* size of the packing area */
66  const vcg::Point2i grid_size(400, 600);
67 
68  PackingParams params;
69  params.costFunction = PackingParams::LowestHorizon;
70  params.doubleHorizon = true;
71  params.innerHorizon = true; /* use inner horizons to pack charts in between gaps */
72  params.permutations = false; /* do not use permutations (they are ignored by PackBestEffort() */
73  params.rotationNum = 16; /* 16 rotations per chart */
74  params.gutterWidth = 2; /* 2 pixels gutter */
75  params.minmax = false; /* do not combine costs of the two horizons when evaluating placements */
76 
77  int totPacked = 0;
78  int nc = 0; /* current container index */
79  while (true) {
80 
81  std::cout << "Packing into container " << nc << std::endl;
82 
83  // build a vector with the outlines not yet packed, and a corresponding vector
84  // of indices into the 'outlines' vector
85  std::vector<int> outlineIndex_iter;
86  std::vector<Outline2f> outlines_iter;
87  for (unsigned i = 0; i < containerIndices.size(); ++i) {
88  if (containerIndices[i] == -1) {
89  outlineIndex_iter.push_back(i);
90  outlines_iter.push_back(outlines[i]);
91  }
92  }
93 
94  std::vector<vcg::Similarity2f> transforms;
95  std::vector<int> polyToContainer;
96  int numPacked = RasterizedPacker::PackBestEffort(outlines_iter, {grid_size}, transforms, polyToContainer, params);
97 
98  totPacked += numPacked;
99 
100  if (numPacked == 0) {
101  std::cerr << "Failed to pack any outline at the current iteration. Stopping." << std::endl;
102  std::exit(-1);
103  } else {
104  for (unsigned i = 0; i < outlines_iter.size(); ++i) {
105  if (polyToContainer[i] != -1) {
106  assert(polyToContainer[i] == 0); // We only use a single container in this example
107  int outline_i = outlineIndex_iter[i];
108  assert(containerIndices[outline_i] == -1);
109  containerIndices[outline_i] = nc;
110  packingTransforms[outline_i] = transforms[i];
111  }
112  }
113  }
114 
115  if (totPacked == outlines.size())
116  break;
117  else
118  nc++;
119 
120  if (nc > 10)
121  std::cerr << "Warning: packing into more than 10 containers! (nc = " << nc << ")" << std::endl;
122  }
123 
124  /* for each container, generate an image */
125  for (int i = 0; i < nc + 1; ++i) {
126  std::vector<Outline2f> outlines_iter;
127  std::vector<vcg::Similarity2f> transforms_iter;
128  for (unsigned k = 0; k < containerIndices.size(); ++k) {
129  assert(containerIndices[k] != -1 && "Some outlines were not packed");
130  if (containerIndices[k] == i) {
131  outlines_iter.push_back(outlines[k]);
132  transforms_iter.push_back(packingTransforms[k]);
133  }
134  }
135  std::string filename = std::string("container_") + std::to_string(i) + std::string(".png");
136  Outline2Dumper::Param pp;
137  pp.width = grid_size.X();
138  pp.height = grid_size.Y();
139  pp.fill = true;
140  pp.randomColor = true;
141 
142  Outline2Dumper::dumpOutline2VecPNG(filename.c_str(), outlines_iter, transforms_iter, pp);
143  }
144 }
145 
146