# C++ PolygonRef::back方法代码示例

## 示例1: calcMinMax

``````void Comb::calcMinMax()
{
int64_t minX_global = INT64_MAX;
int64_t maxX_global = INT64_MIN;
for(unsigned int boundary_poly_idx = 0; boundary_poly_idx < boundary.size(); boundary_poly_idx++)
{
minX[boundary_poly_idx] = INT64_MAX;
maxX[boundary_poly_idx] = INT64_MIN;
PolygonRef poly = boundary[boundary_poly_idx];
Point p0 = transformation_matrix.apply(poly.back());
for(unsigned int boundary_point_idx = 0; boundary_point_idx < poly.size(); boundary_point_idx++)
{
Point p1 = transformation_matrix.apply(poly[boundary_point_idx]);
if ((p0.Y > transformed_startPoint.Y && p1.Y < transformed_startPoint.Y) || (p1.Y > transformed_startPoint.Y && p0.Y < transformed_startPoint.Y))
{
int64_t x = p0.X + (p1.X - p0.X) * (transformed_startPoint.Y - p0.Y) / (p1.Y - p0.Y);

if (x >= transformed_startPoint.X && x <= transformed_endPoint.X)
{
if (x < minX[boundary_poly_idx]) { minX[boundary_poly_idx] = x; minIdx[boundary_poly_idx] = boundary_point_idx; }
if (x > maxX[boundary_poly_idx]) { maxX[boundary_poly_idx] = x; maxIdx[boundary_poly_idx] = boundary_point_idx; }
if (x < minX_global) { minX_global = x; minIdx_global = boundary_poly_idx; }
if (x > maxX_global) { maxX_global = x; maxIdx_global = boundary_poly_idx; }
}
}
p0 = p1;
}
}
}``````

## 示例2: polygonCollidesWithlineSegment

``````bool polygonCollidesWithlineSegment(PolygonRef poly, Point& transformed_startPoint, Point& transformed_endPoint, PointMatrix transformation_matrix)
{
Point p0 = transformation_matrix.apply(poly.back());
for(Point p1_ : poly)
{
Point p1 = transformation_matrix.apply(p1_);
if ((p0.Y > transformed_startPoint.Y && p1.Y < transformed_startPoint.Y) || (p1.Y > transformed_startPoint.Y && p0.Y < transformed_startPoint.Y))
{
int64_t x = p0.X + (p1.X - p0.X) * (transformed_startPoint.Y - p0.Y) / (p1.Y - p0.Y);

if (x > transformed_startPoint.X && x < transformed_endPoint.X)
return true;
}
p0 = p1;
}
return false;
}``````

## 示例3: convertPolygonToList

``````void ListPolyIt::convertPolygonToList(PolygonRef poly, ListPolygon& result)
{
#ifdef DEBUG
Point last = poly.back();
#endif // DEBUG
for (Point& p : poly)
{
result.push_back(p);
#ifdef DEBUG
// usually polygons shouldn't have such degenerate verts
// in PolygonProximityLinker (where this function is (also) used) it is
// required to not have degenerate verts, because verts are mapped
// to links, but if two different verts are at the same place the mapping fails.
assert(p != last);
last = p;
#endif // DEBUG
}
}``````

## 示例4: getClosestPointInPolygon

``````int PathOrderOptimizer::getClosestPointInPolygon(Point prev_point, int poly_idx)
{
PolygonRef poly = polygons[poly_idx];

int best_point_idx = -1;
float best_point_score = std::numeric_limits<float>::infinity();
Point p0 = poly.back();
for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++)
{
Point& p1 = poly[point_idx];
Point& p2 = poly[(point_idx + 1) % poly.size()];
int64_t dist = vSize2(p1 - prev_point);
float is_on_inside_corner_score = -LinearAlg2D::getAngleLeft(p0, p1, p2) / M_PI * 5000 * 5000; // prefer inside corners
// this score is in the order of 5 mm
if (dist + is_on_inside_corner_score < best_point_score)
{
best_point_idx = point_idx;
best_point_score = dist + is_on_inside_corner_score;
}
p0 = p1;
}
return best_point_idx;
}``````

## 示例5: calcScanlineCrossings

``````void LinePolygonsCrossings::calcScanlineCrossings()
{

min_crossing_idx = NO_INDEX;
max_crossing_idx = NO_INDEX;

for(unsigned int poly_idx = 0; poly_idx < boundary.size(); poly_idx++)
{
PolyCrossings minMax(poly_idx);
PolygonRef poly = boundary[poly_idx];
Point p0 = transformation_matrix.apply(poly.back());
for(unsigned int point_idx = 0; point_idx < poly.size(); point_idx++)
{
Point p1 = transformation_matrix.apply(poly[point_idx]);
if ((p0.Y > transformed_startPoint.Y && p1.Y < transformed_startPoint.Y) || (p1.Y > transformed_startPoint.Y && p0.Y < transformed_startPoint.Y))
{
int64_t x = p0.X + (p1.X - p0.X) * (transformed_startPoint.Y - p0.Y) / (p1.Y - p0.Y);

if (x >= transformed_startPoint.X && x <= transformed_endPoint.X)
{
if (x < minMax.min.x) { minMax.min.x = x; minMax.min.point_idx = point_idx; }
if (x > minMax.max.x) { minMax.max.x = x; minMax.max.point_idx = point_idx; }
}
}
p0 = p1;
}

if (minMax.min.point_idx != NO_INDEX)
{ // then also max.point_idx != -1
if (min_crossing_idx == NO_INDEX || minMax.min.x < crossings[min_crossing_idx].min.x) { min_crossing_idx = crossings.size(); }
if (max_crossing_idx == NO_INDEX || minMax.max.x > crossings[max_crossing_idx].max.x) { max_crossing_idx = crossings.size(); }
crossings.push_back(minMax);
}

}
}``````

## 示例6: generateLinearBasedInfill

``````/*
* algorithm:
* 1. for each line segment of each polygon:
*      store the intersections of that line segment with all scanlines in a mapping (vector of vectors) from scanline to intersections
*      (zigzag): add boundary segments to result
* 2. for each scanline:
*      sort the associated intersections
*      and connect them using the even-odd rule
*
* rough explanation of the zigzag algorithm:
* while walking around (each) polygon (1.)
*  if polygon intersects with even scanline
*      start boundary segment (add each following segment to the [result])
*  when polygon intersects with a scanline again
*      stop boundary segment (stop adding segments to the [result])
*  (see infill/ZigzagConnectorProcessor.h for actual implementation details)
*
*
* we call the areas between two consecutive scanlines a 'scansegment'.
* Scansegment x is the area between scanline x and scanline x+1
* Edit: the term scansegment is wrong, since I call a boundary segment leaving from an even scanline to the left as belonging to an even scansegment,
*  while I also call a boundary segment leaving from an even scanline toward the right as belonging to an even scansegment.
*/
void Infill::generateLinearBasedInfill(const int outline_offset, Polygons& result, const int line_distance, const PointMatrix& rotation_matrix, ZigzagConnectorProcessor& zigzag_connector_processor, const bool connected_zigzags, int64_t extra_shift)
{
if (line_distance == 0)
{
return;
}
if (in_outline.size() == 0)
{
return;
}

int shift = extra_shift + this->shift;

Polygons outline;
if (outline_offset != 0)
{
outline = in_outline.offset(outline_offset);
if (perimeter_gaps)
{
}
}
else
{
outline = in_outline;
}

outline = outline.offset(infill_overlap);

if (outline.size() == 0)
{
return;
}

outline.applyMatrix(rotation_matrix);

if (shift < 0)
{
shift = line_distance - (-shift) % line_distance;
}
else
{
shift = shift % line_distance;
}

AABB boundary(outline);

int scanline_min_idx = computeScanSegmentIdx(boundary.min.X - shift, line_distance);
int line_count = computeScanSegmentIdx(boundary.max.X - shift, line_distance) + 1 - scanline_min_idx;

std::vector<std::vector<int64_t> > cut_list; // mapping from scanline to all intersections with polygon segments

for(int scanline_idx = 0; scanline_idx < line_count; scanline_idx++)
{
cut_list.push_back(std::vector<int64_t>());
}

for(unsigned int poly_idx = 0; poly_idx < outline.size(); poly_idx++)
{
PolygonRef poly = outline[poly_idx];
Point p0 = poly.back();
zigzag_connector_processor.registerVertex(p0); // always adds the first point to ZigzagConnectorProcessorEndPieces::first_zigzag_connector when using a zigzag infill type
for(unsigned int point_idx = 0; point_idx < poly.size(); point_idx++)
{
Point p1 = poly[point_idx];
if (p1.X == p0.X)
{
zigzag_connector_processor.registerVertex(p1);
// TODO: how to make sure it always adds the shortest line? (in order to prevent overlap with the zigzag connectors)
// note: this is already a problem for normal infill, but hasn't really cothered anyone so far.
p0 = p1;
continue;
}

int scanline_idx0;
int scanline_idx1;
// this way of handling the indices takes care of the case where a boundary line segment ends exactly on a scanline:
//.........这里部分代码省略.........
``````

## 示例7: findInside

``````unsigned int Polygons::findInside(Point p, bool border_result)
{
Polygons& thiss = *this;
if (size() < 1)
{
return false;
}

int64_t min_x[size()];
std::fill_n(min_x, size(), std::numeric_limits<int64_t>::max());  // initialize with int.max
int crossings[size()];
std::fill_n(crossings, size(), 0);  // initialize with zeros

for (unsigned int poly_idx = 0; poly_idx < size(); poly_idx++)
{
PolygonRef poly = thiss[poly_idx];
Point p0 = poly.back();
for(Point& p1 : poly)
{
short comp = pointLiesOnTheRightOfLine(p, p0, p1);
if (comp == 1)
{
crossings[poly_idx]++;
int64_t x;
if (p1.Y == p0.Y)
{
x = p0.X;
}
else
{
x = p0.X + (p1.X-p0.X) * (p.Y-p0.Y) / (p1.Y-p0.Y);
}
if (x < min_x[poly_idx])
{
min_x[poly_idx] = x;
}
}
else if (border_result && comp == 0)
{
return poly_idx;
}
p0 = p1;
}
}

int64_t min_x_uneven = std::numeric_limits<int64_t>::max();
unsigned int ret = NO_INDEX;
unsigned int n_unevens = 0;
for (unsigned int array_idx = 0; array_idx < size(); array_idx++)
{
if (crossings[array_idx] % 2 == 1)
{
n_unevens++;
if (min_x[array_idx] < min_x_uneven)
{
min_x_uneven = min_x[array_idx];
ret = array_idx;
}
}
}
if (n_unevens % 2 == 0) { ret = NO_INDEX; }
return ret;
}``````

## 示例8: moveInside

``````unsigned int moveInside(Polygons& polygons, Point& from, int distance, int64_t maxDist2)
{
Point ret = from;
int64_t bestDist2 = maxDist2;
unsigned int bestPoly = NO_INDEX;
for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
{
PolygonRef poly = polygons[poly_idx];
if (poly.size() < 2)
continue;
Point p0 = poly[poly.size()-2];
Point p1 = poly.back();
bool projected_p_beyond_prev_segment = dot(p1 - p0, from - p0) > vSize2(p1 - p0);
for(Point& p2 : poly)
{
// X = A + Normal( B - A ) * ((( B - A ) dot ( P - A )) / VSize( A - B ));
// X = P projected on AB
Point& a = p1;
Point& b = p2;
Point& p = from;
Point ab = b - a;
Point ap = p - a;
int64_t ab_length = vSize(ab);
int64_t ax_length = dot(ab, ap) / ab_length;
if (ax_length < 0) // x is projected to before ab
{
if (projected_p_beyond_prev_segment)
{ //  case which looks like:   > .
projected_p_beyond_prev_segment = false;
Point& x = p1;

int64_t dist2 = vSize2(x - p);
if (dist2 < bestDist2)
{
bestDist2 = dist2;
if (distance == 0) { ret = x; }
else { ret = x + normal(crossZ(normal(a, distance*4) + normal(p1 - p0, distance*4)), distance); } // *4 to retain more precision for the eventual normalization
bestPoly = poly_idx;
}
}
else
{
projected_p_beyond_prev_segment = false;
p0 = p1;
p1 = p2;
continue;
}
}
else if (ax_length > ab_length) // x is projected to beyond ab
{
projected_p_beyond_prev_segment = true;
p0 = p1;
p1 = p2;
continue;
}
else
{
projected_p_beyond_prev_segment = false;
Point x = a + ab * ax_length / ab_length;

int64_t dist2 = vSize2(x - from);
if (dist2 < bestDist2)
{
bestDist2 = dist2;
if (distance == 0) { ret = x; }
else { ret = x + crossZ(normal(ab, distance)); }
bestPoly = poly_idx;
}
}

p0 = p1;
p1 = p2;
}
}
if (bestDist2 < maxDist2)
{
from = ret;
return bestPoly;
}
return NO_INDEX;
}``````