-
Notifications
You must be signed in to change notification settings - Fork 4
/
layout1d.cpp
136 lines (129 loc) · 4.13 KB
/
layout1d.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "stdafx.h"
#include <algorithm>
#include "layout1d.h"
namespace Denisenko {
namespace Raskroy {
// 1D layout recursion
// Parameters:
// [i] size - maximum size where to fit segments
// [o] rashod - consumption of segments
// this:
// [io] m_pOtherSize
// [i] m_pEndOtherSize
// [i] m_remains
scalar Layout1d::Recursion(scalar i_size, std::list<std::pair<const OtherSize*, unsigned> > & layout)
{
unsigned amount = 0;
std::for_each(m_pOtherSize->parts.begin(), m_pOtherSize->parts.end(),
[&amount, this](Part * part){amount += (*m_remains)[part->AmountOffset];});
if (m_pOtherSize != m_pEndOtherSize)
{
scalar bestRemain = i_size;
bool first = true;
scalar size = i_size;
unsigned n = 0;
while (n <= amount && size > m_sawThickness)
{
scalar remain;
std::list<std::pair<const OtherSize *, unsigned> > sublayout;
m_pOtherSize++;
remain = Recursion(size, sublayout);
m_pOtherSize--;
if (remain < bestRemain || first)
{
bestRemain = remain;
sublayout.push_front(std::make_pair(&*m_pOtherSize, n));
layout.swap(sublayout);
if (bestRemain <= 0) // this is the best possible
return bestRemain;
first = false;
}
size -= m_pOtherSize->Value + m_sawThickness;
n++;
// here size can be < 0 which is ok if remain is smaller than
// the saw size
}
// if nothing layed out return zeros
//if (best == size)
//{
// rashod.resize(remains.size());
// std::fill(rashod.begin(), rashod.end(), 0);
//}
return bestRemain;
}
else
{
scalar fullSize = m_pOtherSize->Value + m_sawThickness;
unsigned n = unsigned((i_size + m_sawThickness) / fullSize);
if (n > amount)
n = amount;
layout.clear();
layout.push_back(std::make_pair(&*m_pOtherSize, n));
//o_rashods.resize(m_remains->size());
// here size can be < 0 which is ok if remain is smaller than
// the saw size
return i_size - n * fullSize;
}
}
// 1D layout
// Parameters:
// [i] size - list of segments is in size.other_sizes
// [i] other_size - target size
// [o] stat - statistics
// [o] details - layout result, empty container should be passed on input
// [o] rashod - consumption of segments
// Returns true if has layout
bool Layout1d::Make(const Size &size, scalar otherSize, OldLayoutResult::Details &o_details, Amounts &o_rashods, scalar &o_remain, double &o_opilki)
{
if (otherSize < size.other_sizes.Min->Value)
return false;
// setting up variables for recursion
m_pOtherSize = size.other_sizes.begin();
m_pEndOtherSize = size.other_sizes.end();
m_pEndOtherSize--;
// recursively try sizes [i..end]
std::list<std::pair<const OtherSize *, unsigned> > layout;
scalar remain = Recursion(otherSize, layout);
if (remain == otherSize) // if nothing was layed out
return false;
auto cuts = 0; // number of cuts
for (auto sz = layout.begin(); sz != layout.end(); sz++)
{
auto consumed = sz->second;
auto os = sz->first;
if (consumed > 0)
{
auto consume_remain = consumed;
OldLayoutResult::Detail detail;
// fill o_rashods
// and fill parts attribute
for (auto part_iter = os->parts.begin();
part_iter != os->parts.end(); part_iter++)
{
auto ppart = *part_iter;
auto part_remain = (*m_remains)[ppart->AmountOffset];
auto to_consume = std::min(part_remain, consume_remain);
o_rashods[ppart->AmountOffset] += to_consume;
consume_remain -= to_consume;
detail.parts.push_back(std::make_pair(ppart, to_consume));
}
detail.size = sz->first->Value;
detail.num = consumed;
o_details.push_back(detail);
cuts += consumed; // number of cuts
}
}
// Calculating sawdust
double opilki = (double)size.Value * (double)m_sawThickness * (double)cuts;
// If last cut is't full than reduce sawdust
if (remain < 0)
{
opilki += (double)size.Value * (double)remain;
remain = 0;
}
o_opilki = opilki;
o_remain = remain;
return true;
}
} // namespace Denisenko
} // namespace Raskroy