mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-21 15:51:10 -06:00
Ported Slic3r::Geometry::arrange() to C++/XS
This commit is contained in:
parent
5eb3bc52ef
commit
d6d7880507
6 changed files with 160 additions and 120 deletions
|
@ -161,6 +161,133 @@ simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
|
|||
Slic3r::simplify_polygons(pp, retval);
|
||||
}
|
||||
|
||||
double
|
||||
linint(double value, double oldmin, double oldmax, double newmin, double newmax)
|
||||
{
|
||||
return (value - oldmin) * (newmax - newmin) / (oldmax - oldmin) + newmin;
|
||||
}
|
||||
|
||||
Pointfs
|
||||
arrange(size_t total_parts, Pointf part, coordf_t dist, const BoundingBoxf &bb)
|
||||
{
|
||||
// use actual part size (the largest) plus separation distance (half on each side) in spacing algorithm
|
||||
part.x += dist;
|
||||
part.y += dist;
|
||||
|
||||
Pointf area;
|
||||
if (bb.defined) {
|
||||
area = bb.size();
|
||||
} else {
|
||||
// bogus area size, large enough not to trigger the error below
|
||||
area.x = part.x * total_parts;
|
||||
area.y = part.y * total_parts;
|
||||
}
|
||||
|
||||
// this is how many cells we have available into which to put parts
|
||||
size_t cellw = floor((area.x + dist) / part.x);
|
||||
size_t cellh = floor((area.x + dist) / part.x);
|
||||
|
||||
if (total_parts > (cellw * cellh))
|
||||
CONFESS("%zu parts won't fit in your print area!\n", total_parts);
|
||||
|
||||
// total space used by cells
|
||||
Pointf cells(cellw * part.x, cellh * part.y);
|
||||
|
||||
// bounding box of total space used by cells
|
||||
BoundingBoxf cells_bb;
|
||||
cells_bb.merge(Pointf(0,0)); // min
|
||||
cells_bb.merge(cells); // max
|
||||
|
||||
// center bounding box to area
|
||||
cells_bb.translate(
|
||||
-(area.x - cells.x) / 2,
|
||||
-(area.y - cells.y) / 2
|
||||
);
|
||||
|
||||
// list of cells, sorted by distance from center
|
||||
std::vector<ArrangeItemIndex> cellsorder;
|
||||
|
||||
// work out distance for all cells, sort into list
|
||||
for (size_t i = 0; i <= cellw-1; ++i) {
|
||||
for (size_t j = 0; j <= cellh-1; ++j) {
|
||||
coordf_t cx = linint(i + 0.5, 0, cellw, cells_bb.min.x, cells_bb.max.x);
|
||||
coordf_t cy = linint(j + 0.5, 0, cellh, cells_bb.max.y, cells_bb.min.y);
|
||||
|
||||
coordf_t xd = fabs((area.x / 2) - cx);
|
||||
coordf_t yd = fabs((area.y / 2) - cy);
|
||||
|
||||
ArrangeItem c;
|
||||
c.pos.x = cx;
|
||||
c.pos.y = cy;
|
||||
c.index_x = i;
|
||||
c.index_y = j;
|
||||
c.dist = xd * xd + yd * yd - fabs((cellw / 2) - (i + 0.5));
|
||||
|
||||
// binary insertion sort
|
||||
{
|
||||
coordf_t index = c.dist;
|
||||
size_t low = 0;
|
||||
size_t high = cellsorder.size();
|
||||
while (low < high) {
|
||||
size_t mid = (low + ((high - low) / 2)) | 0;
|
||||
coordf_t midval = cellsorder[mid].index;
|
||||
|
||||
if (midval < index) {
|
||||
low = mid + 1;
|
||||
} else if (midval > index) {
|
||||
high = mid;
|
||||
} else {
|
||||
cellsorder.insert(cellsorder.begin() + mid, ArrangeItemIndex(index, c));
|
||||
goto ENDSORT;
|
||||
}
|
||||
}
|
||||
cellsorder.insert(cellsorder.begin() + low, ArrangeItemIndex(index, c));
|
||||
}
|
||||
ENDSORT: true;
|
||||
}
|
||||
}
|
||||
|
||||
// the extents of cells actually used by objects
|
||||
coordf_t lx = 0;
|
||||
coordf_t ty = 0;
|
||||
coordf_t rx = 0;
|
||||
coordf_t by = 0;
|
||||
|
||||
// now find cells actually used by objects, map out the extents so we can position correctly
|
||||
for (size_t i = 1; i <= total_parts; ++i) {
|
||||
ArrangeItemIndex c = cellsorder[i - 1];
|
||||
coordf_t cx = c.item.index_x;
|
||||
coordf_t cy = c.item.index_y;
|
||||
if (i == 1) {
|
||||
lx = rx = cx;
|
||||
ty = by = cy;
|
||||
} else {
|
||||
if (cx > rx) rx = cx;
|
||||
if (cx < lx) lx = cx;
|
||||
if (cy > by) by = cy;
|
||||
if (cy < ty) ty = cy;
|
||||
}
|
||||
}
|
||||
// now we actually place objects into cells, positioned such that the left and bottom borders are at 0
|
||||
Pointfs positions;
|
||||
for (size_t i = 1; i <= total_parts; ++i) {
|
||||
ArrangeItemIndex c = cellsorder.front();
|
||||
cellsorder.erase(cellsorder.begin());
|
||||
coordf_t cx = c.item.index_x - lx;
|
||||
coordf_t cy = c.item.index_y - ty;
|
||||
|
||||
positions.push_back(Pointf(cx * part.x, cy * part.y));
|
||||
}
|
||||
|
||||
if (bb.defined) {
|
||||
for (Pointfs::iterator p = positions.begin(); p != positions.end(); ++p) {
|
||||
p->x += bb.min.x;
|
||||
p->y += bb.min.y;
|
||||
}
|
||||
}
|
||||
return positions;
|
||||
}
|
||||
|
||||
Line
|
||||
MedialAxis::edge_to_line(const VD::edge_type &edge) const
|
||||
{
|
||||
|
|
|
@ -23,6 +23,21 @@ double rad2deg_dir(double angle);
|
|||
double deg2rad(double angle);
|
||||
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval);
|
||||
|
||||
class ArrangeItem {
|
||||
public:
|
||||
Pointf pos;
|
||||
size_t index_x, index_y;
|
||||
coordf_t dist;
|
||||
};
|
||||
class ArrangeItemIndex {
|
||||
public:
|
||||
coordf_t index;
|
||||
ArrangeItem item;
|
||||
ArrangeItemIndex(coordf_t _index, ArrangeItem _item) : index(_index), item(_item) {};
|
||||
};
|
||||
double linint(double value, double oldmin, double oldmax, double newmin, double newmax);
|
||||
Pointfs arrange(size_t total_parts, Pointf part, coordf_t dist, const BoundingBoxf &bb = BoundingBoxf());
|
||||
|
||||
class MedialAxis {
|
||||
public:
|
||||
Points points;
|
||||
|
|
|
@ -4,7 +4,7 @@ use strict;
|
|||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 8;
|
||||
use Test::More tests => 9;
|
||||
|
||||
use constant PI => 4 * atan2(1, 1);
|
||||
|
||||
|
@ -31,4 +31,11 @@ use constant PI => 4 * atan2(1, 1);
|
|||
ok !Slic3r::Geometry::directions_parallel_within(PI/2, PI, 0), 'directions_parallel_within';
|
||||
ok !Slic3r::Geometry::directions_parallel_within(PI/2, PI, PI/180), 'directions_parallel_within';
|
||||
}
|
||||
|
||||
{
|
||||
my $positions = Slic3r::Geometry::arrange(4, Slic3r::Pointf->new(20, 20),
|
||||
5, Slic3r::Geometry::BoundingBoxf->new);
|
||||
is scalar(@$positions), 4, 'arrange() returns expected number of positions';
|
||||
}
|
||||
|
||||
__END__
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
%package{Slic3r::Geometry};
|
||||
|
||||
Pointfs arrange(size_t total_parts, Pointf* part, coordf_t dist, BoundingBoxf* bb)
|
||||
%code{% RETVAL = Slic3r::Geometry::arrange(total_parts, *part, dist, *bb); %};
|
||||
|
||||
%{
|
||||
|
||||
bool
|
||||
|
@ -87,6 +90,7 @@ simplify_polygons(polygons, tolerance)
|
|||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
||||
IV
|
||||
_constant()
|
||||
ALIAS:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue