Jump to content

Sutherland-Hodgman polygon clipping: Difference between revisions

Line 1,712:
=={{header|C++}}==
 
<syntaxhighlight lang="cpp">#include <iostream>
 
#include <iostream>
using namespace std;
#include <span>
#include <vector>
 
struct point2Dvec2 { float x, y; };
float x = 0.0f, y = 0.0f;
 
constexpr vec2 operator+(vec2 other) const {
const int N = 99; // clipped (new) polygon size
return vec2{x + other.x, y + other.y};
}
 
constexpr vec2 operator-(vec2 other) const {
return vec2{x - other.x, y - other.y};
}
};
 
constexpr vec2 operator*(vec2 a, float b) { return vec2{a.x * b, a.y * b}; }
 
constexpr float dot(vec2 a, vec2 b) { return a.x * b.x + a.y * b.y; }
 
constexpr float cross(vec2 a, vec2 b) { return a.x * b.y - b.x * a.y; }
 
// check if a point is on the LEFT side of an edge
constexpr bool insideis_inside(point2Dvec2 ppoint, point2Dvec2 p1a, point2Dvec2 p2b) {
return (cross(a - b, point) + cross(b, a)) < 0.0f;
{
return (p2.y - p1.y) * p.x + (p1.x - p2.x) * p.y + (p2.x * p1.y - p1.x * p2.y) < 0;
}
 
// calculate intersection point
point2Dconstexpr vec2 intersection(point2Dvec2 cp1a1, point2Dvec2 cp2a2, point2Dvec2 sb1, point2Dvec2 eb2) {
return ((b1 - b2) * cross(a1, a2) - (a1 - a2) * cross(b1, b2)) *
{
point2D dc = { cp1 (1.x0f / cross(a1 - cp2.xa2, cp1.yb1 - cp2.y }b2));
point2D dp = { s.x - e.x, s.y - e.y };
 
float n1 = cp1.x * cp2.y - cp1.y * cp2.x;
float n2 = s.x * e.y - s.y * e.x;
float n3 = 1.0 / (dc.x * dp.y - dc.y * dp.x);
 
return { (n1 * dp.x - n2 * dc.x) * n3, (n1 * dp.y - n2 * dc.y) * n3 };
}
 
// Sutherland-Hodgman clipping
std::vector<vec2> suther_land_hodgman(
void SutherlandHodgman(point2D *subjectPolygon, int &subjectPolygonSize, point2D *clipPolygon, int &clipPolygonSize, point2D (&newPolygon)[N], int &newPolygonSize)
std::span<vec2 const> subject_polygon, std::span<vec2 const> clip_polygon) {
{
if (clip_polygon.empty() || subject_polygon.empty()) {
point2D cp1, cp2, s, e, inputPolygon[N];
return {};
}
 
std::vector<vec2> ring{subject_polygon.begin(), subject_polygon.end()};
// copy subject polygon to new polygon and set its size
for(int i = 0; i < subjectPolygonSize; i++)
newPolygon[i] = subjectPolygon[i];
 
vec2 p1 = clip_polygon[clip_polygon.size() - 1];
newPolygonSize = subjectPolygonSize;
 
std::vector<vec2> input;
for(int j = 0; j < clipPolygonSize; j++)
{
// copy new polygon to input polygon & set counter to 0
for(int k = 0; k < newPolygonSize; k++){ inputPolygon[k] = newPolygon[k]; }
int counter = 0;
 
for (vec2 p2 : clip_polygon) {
// get clipping polygon edge
cp1 = clipPolygon[j]input.clear();
input.insert(input.end(), ring.begin(), ring.end());
cp2 = clipPolygon[(j + 1) % clipPolygonSize];
vec2 s = input[input.size() - 1];
 
ring.clear();
for(int i = 0; i < newPolygonSize; i++)
{
// get subject polygon edge
s = inputPolygon[i];
e = inputPolygon[(i + 1) % newPolygonSize];
 
for (vec2 e // Case 1: Bothinput) vertices are inside:{
//if Only(is_inside(e, thep1, secondp2)) vertex is added to the output list{
if(inside(s, cp1, cp2) && insideif (e!is_inside(s, cp1p1, cp2p2)) {
newPolygon[counter++] = ring.push_back(intersection(p1, p2, s, e));
}
 
// Case 2: First vertex is outside while second one is inside:ring.push_back(e);
//} Bothelse theif point(is_inside(s, ofp1, intersectionp2)) of the edge with the clip boundary{
// and the second vertexring.push_back(intersection(p1, arep2, addeds, to the output liste));
else if(!inside(s, cp1, cp2) && inside(e, cp1, cp2))
{
newPolygon[counter++] = intersection(cp1, cp2, s, e);
newPolygon[counter++] = e;
}
 
s = e;
// Case 3: First vertex is inside while second one is outside:
}
// Only the point of intersection of the edge with the clip boundary
// is added to the output list
else if(inside(s, cp1, cp2) && !inside(e, cp1, cp2))
newPolygon[counter++] = intersection(cp1, cp2, s, e);
 
p1 = p2;
// Case 4: Both vertices are outside
else if(!inside(s, cp1, cp2) && !inside(e, cp1, cp2))
{
// No vertices are added to the output list
}
}
// set new polygon size
newPolygonSize = counter;
}
 
return ring;
}
 
int main(int argc, char ** argv) {
{
// subject polygon
vec2 subject_polygon[] = {{50, 150}, {200, 50}, {350, 150},
point2D subjectPolygon[] = {
{50350,150 300}, {200250,50 300}, {350200,150 250},
{150, 350,300}, {100, 250,300}, {100, 200,250},};
{150,350},{100,250},{100,200}
};
int subjectPolygonSize = sizeof(subjectPolygon) / sizeof(subjectPolygon[0]);
 
// clipping polygon
point2Dvec2 clipPolygonclip_polygon[] = { {100, 100}, {300, 100}, {300, 300}, {100, 300} };
int clipPolygonSize = sizeof(clipPolygon) / sizeof(clipPolygon[0]);
 
// define the new clipped polygon (empty)
int newPolygonSize = 0;
point2D newPolygon[N] = { 0 };
 
// apply clipping
std::vector<vec2> clipped_polygon =
SutherlandHodgman(subjectPolygon, subjectPolygonSize, clipPolygon, clipPolygonSize, newPolygon, newPolygonSize);
suther_land_hodgman(subject_polygon, clip_polygon);
 
// print clipped polygon points
std::cout << "Clipped polygon points:" << std::endl;
for (intvec2 ip =: 0;clipped_polygon) i < newPolygonSize; i++){
std::cout << "(" << newPolygon[i]p.x << ", " << newPolygon[i]p.y << ")" << std::endl;
}
 
return 0EXIT_SUCCESS;
}
 
</syntaxhighlight>
{{out}}
<pre>
<pre>Clipped polygon points:
Clipped polygon points:
(100, 116.667)
(125, 100)
(275, 100)
(300, 116.667)
(300, 300)
(250, 300)
Line 1,834 ⟶ 1,823:
(125, 300)
(100, 250)
</pre>
(100, 116.667)
(125, 100)
(275, 100)
(300, 116.667)</pre>
 
=={{header|D}}==
1

edit

Cookies help us deliver our services. By using our services, you agree to our use of cookies.