Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/geos/operation/buffer/OffsetSegmentGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ class GEOS_DLL OffsetSegmentGenerator {
/// Add an end cap around point p1, terminating a line segment
/// coming from p0
void addLineEndCap(const geom::Coordinate& p0,
const geom::Coordinate& p1);
const geom::Coordinate& p1,
const geom::Coordinate& p2);

void
addSegments(const geom::CoordinateSequence& pts, bool isForward)
Expand Down
8 changes: 5 additions & 3 deletions src/operation/buffer/OffsetCurveBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,6 @@ OffsetCurveBuilder::computeLineBufferCurve(const CoordinateSequence& inputPts,
segGen.addNextSegment(simp1[i], true);
}
segGen.addLastSegment();
// add line cap for end of line
segGen.addLineEndCap(simp1[n1 - 1], simp1[n1]);

//---------- compute points for right side of line
// Simplify the appropriate side of the line before generating
Expand All @@ -387,13 +385,17 @@ OffsetCurveBuilder::computeLineBufferCurve(const CoordinateSequence& inputPts,
const CoordinateSequence& simp2 = *simp2_;

auto n2 = simp2.size() - 1;

// add line cap for return of line
segGen.addLineEndCap(simp1[n1 - 1], simp1[n1], simp2[n2 - 1]);

segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position::LEFT);
for(std::size_t i = n2 - 1; i > 0; --i) {
segGen.addNextSegment(simp2[i - 1], true);
}
segGen.addLastSegment();
// add line cap for start of line
segGen.addLineEndCap(simp2[1], simp2[0]);
segGen.addLineEndCap(simp2[1], simp2[0], simp1[1]);

segGen.closeRing();
}
Expand Down
21 changes: 11 additions & 10 deletions src/operation/buffer/OffsetSegmentGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,25 +187,21 @@ OffsetSegmentGenerator::computeOffsetSegment(const LineSegment& seg, int p_side,

/*public*/
void
OffsetSegmentGenerator::addLineEndCap(const Coordinate& p0, const Coordinate& p1)
OffsetSegmentGenerator::addLineEndCap(const Coordinate& p0, const Coordinate& p1, const Coordinate& p2)
{
LineSegment seg(p0, p1);
LineSegment segL(p0, p1);
LineSegment segR(p2, p1);

LineSegment offsetL;
computeOffsetSegment(seg, Position::LEFT, distance, offsetL);
computeOffsetSegment(segL, Position::LEFT, distance, offsetL);
LineSegment offsetR;
computeOffsetSegment(seg, Position::RIGHT, distance, offsetR);

double dx = p1.x - p0.x;
double dy = p1.y - p0.y;
double angle = atan2(dy, dx);
computeOffsetSegment(segR, Position::RIGHT, distance, offsetR);

switch(bufParams.getEndCapStyle()) {
case BufferParameters::CAP_ROUND:
// add offset seg points with a fillet between them
segList.addPt(offsetL.p1);
addDirectedFillet(p1, angle + Angle::PI_OVER_2, angle - Angle::PI_OVER_2,
Orientation::CLOCKWISE, distance);
addDirectedFillet(p1, offsetL.p1, offsetR.p1, Orientation::CLOCKWISE, distance);
segList.addPt(offsetR.p1);
break;
case BufferParameters::CAP_FLAT:
Expand All @@ -216,7 +212,12 @@ OffsetSegmentGenerator::addLineEndCap(const Coordinate& p0, const Coordinate& p1
case BufferParameters::CAP_SQUARE:
// add a square defined by extensions of the offset
// segment endpoints

Coordinate squareCapSideOffset;
// take average in case angles of left and right sides differ
double dx = p1.x - p0.x/2 - p2.x/2;
double dy = p1.y - p0.y/2 - p2.y/2;
double angle = atan2(dy, dx);
double sinangle, cosangle;
Angle::sinCosSnap(angle, sinangle, cosangle);
squareCapSideOffset.x = fabs(distance) * cosangle;
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/operation/buffer/BufferOpTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,4 +623,18 @@ void object::test<28>
"MULTIPOLYGON (((24 95.239, 24 96, 24 99, 24.816 99, 24 95.239)), ((3 90, 3 93, 3 96, 3 99, 21 99, 21 96, 21 93, 21 90, 3 90)))");
}

// testEndCap
// test end cap for a line where left and right side are simplified differently, so there is an angle at the end
// See https://github.com/libgeos/geos/issues/1217
template<>
template<>
void object::test<29>
()
{
std::string wkt("LINESTRING (0.7 4.7, 146.3 137.1, 146.3 137, 146.6 136.7)");
std::unique_ptr<Geometry> result13 = buffer(wkt, 11);
checkValidPolygon(*result13);
checkNumHoles(*result13, 0);
}

} // namespace tut
Loading