|
Boost : |
Subject: [boost] [GGL][Polygon][Union] Union of multi_polygon returns unexpected
From: Mohammad Morshed Alam Helal (helal_at_[hidden])
Date: 2010-02-05 09:44:40
Hello Barend,
Union of multi_polygon has some bugs. I must admit I could not pinpoint
the problem. Please let me know if I am missing something.
These are the test cases I tried and most of them failed:
Case 5: both list has equal number of polygon (PASS)
Case 6: one of the list has a single polygon (FAIL)
Case 7: both list has one polygon (intersecting) (PASS)
Case 8: Different number of polygons in the lists (FAIL)
Case 9: 2nd list has a single polygon (FAIL)
Case 10: both list has one polygon (non-intersecting) (PASS)
Case 11: one list has same polygon twice (FAIL)
Case 12A: using same list twice. Its a mess. (FAIL)
Case 12B: keeping one of the list empty. Returns empty. (FAIL)
Images from Case 9:
Before:
Multi_polygon 1:
****************************
****************************
****************************
******** ********
******* X *******
****** XXX ******
***** *****
**** Y ****
***** YYYS *****
****** S SS ******
******* XXXX *******
******** ********
****************************
****************************
****************************
Multi_polygon 1: (only the X marked area)
............................
............................
............................
........ ........
....... ..X....
...... XXX....
..... XXX.....
.... XX ....
..... .....
...... ......
....... .......
........ ........
............................
............................
............................
After:
Multi_polygon:
****************************
****************************
****************************
******** ********
******* *******
****** *******
***** ********
**** ** ****
***** *****
****** ******
******* *******
******** ********
****************************
****************************
****************************
As you see, the floating polygons are missing.
You can use the code below to regenerate the cases.
I have the PPM images. Please let me know if you need them.
Thank you for the fixes for the previous problem with union of polygons.
It worked.
Best regards,
Helal
//@_Begin_of_Code
void uniontest()
{
bool case_1 = false,
case_2 = false,
case_2_3 = false,
case_4 = false,
case_5 = true,
case_6 = true,
case_7 = true,
case_8 = true,
case_9 = true,
case_10 = true,
case_11 = true,
case_12 = true,
isDump = false;
double L = 200.0;
const double outloop[][2] = { {L, L}, {L, -L}, {-L, -L}, {-L, L},
{L, L} };
double R = 100.0;
double H = R * sqrt(3.0) / 2;
const double inloop[][2] = { {R, 0}, {R/2, -H}, {-R/2, -H}, {-R,
0}, {-R/2, H}, {R/2, H}, {R, 0} };
polygon_2d BIGpoly; //A
rectangle with a hexagonal hole in it
assign(BIGpoly, outloop); //the rectangle
BIGpoly.inners().resize(1);
linear_ring<point_2d>& inner = BIGpoly.inners().back();
assign(inner, inloop); //the inner
hexagon
correct(BIGpoly); //correct
the order iff not
double a = 20.0;
double h = a * sqrt(3.0) / 2;
const double t1[][2] = { { 30+0, 10+0}, { 30+a/2, 10+h}, { 30+a,
10+0} };
const double t2[][2] = { { 0, 0}, { a/2, h}, {
a, 0} };
const double t3[][2] = { {-10+0, -10+0}, {-10+a/2, -10+h}, {-10+a,
-10+0} };
const double t4[][2] = { { 0, -15+0}, { a/2, -15+h}, { a,
-15+0} };
const double t5[][2] = { {-50, -40}, {-110, 0}, {-100, 30}, {-50,
-40} };
polygon_2d T1, T2, T3, T4, T5, T6;
//the triangles
assign(T1, t1);
correct(T1);
assign(T2, t2);
correct(T2);
assign(T3, t3);
correct(T3);
assign(T4, t4);
correct(T4);
assign(T5, t5);
correct(T5);
std::vector<polygon_2d > P_list, P_union, P_tmp;
//the outer shape
P_union.push_back(BIGpoly);
if (isDump) DumbPPMPrint("c:\\BIGpoly.ppm", P_union.begin(),
P_union.size());
//Case 1: floating triangle in hole
if (case_1)
{
P_union.clear();
union_inserter<polygon_2d >(BIGpoly, T1,
std::back_inserter(P_union));
if (isDump) DumbPPMPrint("c:\\case1.ppm", P_union.begin(),
P_union.size());
}
//Case 2: three solid triangle creating a small hole
if (case_2)
{
P_union.clear();
P_tmp.clear();
union_inserter<polygon_2d >(T2, T3, std::back_inserter(P_tmp));
if (isDump) DumbPPMPrint("c:\\case2_i.ppm", P_tmp.begin(),
P_tmp.size());
union_inserter<polygon_2d >( (*(P_tmp.begin())), T4,
std::back_inserter(P_union));
if (isDump) DumbPPMPrint("c:\\case2.ppm", P_union.begin(),
P_union.size());
}
//Case 3: floating holed-polygon in hole
if (case_2_3)
{
//P_union.clear(); //contains result of case 2
P_tmp.clear();
union_inserter<polygon_2d >(BIGpoly, (*(P_union.begin())),
std::back_inserter(P_tmp));
if (isDump) DumbPPMPrint("c:\\case3.ppm", P_tmp.begin(),
P_tmp.size());
}
//Case 4: a triangle intersecting the hole from inside
if (case_4)
{
P_union.clear();
P_union.push_back(BIGpoly);
P_union.push_back(T5);
if (isDump) DumbPPMPrint("c:\\case4_pre.ppm", P_union.begin(),
P_union.size());
P_union.clear();
union_inserter<polygon_2d >( BIGpoly, T5,
std::back_inserter(P_union));
if (isDump) DumbPPMPrint("c:\\case4.ppm", P_union.begin(),
P_union.size());
P_union.clear();
union_inserter<polygon_2d >( T5, BIGpoly,
std::back_inserter(P_union));
if (isDump) DumbPPMPrint("c:\\case4_rev_order.ppm",
P_union.begin(), P_union.size());
}
//Case 5: using multi_polygon (PASS)
// both list has equal number of polygon
if (case_5)
{
typedef multi_polygon<polygon_2d> polygon_set;
polygon_set ps1, ps2, ps3;
ps1.push_back(BIGpoly);
ps1.push_back(T1);
ps1.push_back(T2);
ps2.push_back(T3);
ps2.push_back(T4);
ps2.push_back(T5);
union_inserter<polygon_2d>(ps1, ps2, std::back_inserter(ps3));
if (isDump) DumbPPMPrint("c:\\case5.ppm", ps3.begin(), ps3.size());
if (isDump) DumbPPMPrint("c:\\case5_A.ppm", ps1.begin(),
ps1.size());
if (isDump) DumbPPMPrint("c:\\case5_B.ppm", ps2.begin(),
ps2.size());
}
//Case 6: using multi_polygon (FAIL)
// one of the list has a single polygon
if (case_6)
{
typedef multi_polygon<polygon_2d> polygon_set;
polygon_set ps1, ps2, ps3;
ps1.push_back(BIGpoly);
ps2.push_back(T1);
ps2.push_back(T2);
ps2.push_back(T3);
ps2.push_back(T4);
ps2.push_back(T5);
union_inserter<polygon_2d>(ps1, ps2, std::back_inserter(ps3));
if (isDump) DumbPPMPrint("c:\\case6.ppm", ps3.begin(), ps3.size());
if (isDump) DumbPPMPrint("c:\\case6_A.ppm", ps1.begin(),
ps1.size());
if (isDump) DumbPPMPrint("c:\\case6_B.ppm", ps2.begin(),
ps2.size());
}
//Case 7: using multi_polygon (PASS)
// both list has one polygon (intersecting)
if (case_7)
{
typedef multi_polygon<polygon_2d> polygon_set;
polygon_set ps1, ps2, ps3;
ps1.push_back(BIGpoly);
ps2.push_back(T5);
union_inserter<polygon_2d>(ps1, ps2, std::back_inserter(ps3));
if (isDump) DumbPPMPrint("c:\\case7.ppm", ps3.begin(), ps3.size());
if (isDump) DumbPPMPrint("c:\\case7_A.ppm", ps1.begin(),
ps1.size());
if (isDump) DumbPPMPrint("c:\\case7_B.ppm", ps2.begin(),
ps2.size());
}
//Case 8: using multi_polygon (FAIL)
// Different number of polygons in the lists
if (case_8)
{
typedef multi_polygon<polygon_2d> polygon_set;
polygon_set ps1, ps2, ps3;
ps1.push_back(BIGpoly);
ps1.push_back(T1);
ps2.push_back(T2);
ps2.push_back(T3);
ps2.push_back(T4);
ps2.push_back(T5);
union_inserter<polygon_2d>(ps1, ps2, std::back_inserter(ps3));
if (isDump) DumbPPMPrint("c:\\case8.ppm", ps3.begin(), ps3.size());
if (isDump) DumbPPMPrint("c:\\case8_A.ppm", ps1.begin(),
ps1.size());
if (isDump) DumbPPMPrint("c:\\case8_B.ppm", ps2.begin(),
ps2.size());
}
//Case 9: using multi_polygon (FAIL)
// 2nd list has a single polygon
if (case_9)
{
typedef multi_polygon<polygon_2d> polygon_set;
polygon_set ps1, ps2, ps3;
ps1.push_back(BIGpoly);
ps1.push_back(T1);
ps1.push_back(T2);
ps1.push_back(T3);
ps1.push_back(T4);
ps2.push_back(T5);
union_inserter<polygon_2d>(ps1, ps2, std::back_inserter(ps3));
if (isDump) DumbPPMPrint("c:\\case9.ppm", ps3.begin(), ps3.size());
if (isDump) DumbPPMPrint("c:\\case9_A.ppm", ps1.begin(),
ps1.size());
if (isDump) DumbPPMPrint("c:\\case9_B.ppm", ps2.begin(),
ps2.size());
}
//Case 10: using multi_polygon (PASS)
// both list has one polygon (non-intersecting)
if (case_10)
{
typedef multi_polygon<polygon_2d> polygon_set;
polygon_set ps1, ps2, ps3;
ps1.push_back(BIGpoly);
ps2.push_back(T4);
union_inserter<polygon_2d>(ps1, ps2, std::back_inserter(ps3));
if (isDump) DumbPPMPrint("c:\\case10.ppm", ps3.begin(),
ps3.size());
if (isDump) DumbPPMPrint("c:\\case10_A.ppm", ps1.begin(),
ps1.size());
if (isDump) DumbPPMPrint("c:\\case10_B.ppm", ps2.begin(),
ps2.size());
}
//Case 11: using multi_polygon (FAIL)
// one list has same polygon twice
if (case_11)
{
typedef multi_polygon<polygon_2d> polygon_set;
polygon_set ps1, ps2, ps3;
ps1.push_back(BIGpoly);
ps2.push_back(T4);
ps2.push_back(T4);
union_inserter<polygon_2d>(ps1, ps2, std::back_inserter(ps3));
if (isDump) DumbPPMPrint("c:\\case11.ppm", ps3.begin(),
ps3.size());
if (isDump) DumbPPMPrint("c:\\case11_A.ppm", ps1.begin(),
ps1.size());
if (isDump) DumbPPMPrint("c:\\case11_B.ppm", ps2.begin(),
ps2.size());
}
//Case 12: using multi_polygon (FAIL)
//A: using same list twice. Its a mess
//B: keeping one of the list empty. Returns empty.
if (case_12)
{
typedef multi_polygon<polygon_2d> polygon_set;
polygon_set ps1, ps2, ps3;
ps1.push_back(BIGpoly);
ps1.push_back(T1);
ps1.push_back(T2);
ps1.push_back(T3);
ps1.push_back(T4);
ps1.push_back(T5);
union_inserter<polygon_2d>(ps1, ps1,
std::back_inserter(ps3)); //A
//union_inserter<polygon_2d>(ps1, ps2,
std::back_inserter(ps3)); //B
if (isDump) DumbPPMPrint("c:\\case12.ppm", ps3.begin(),
ps3.size());
if (isDump) DumbPPMPrint("c:\\case12_A.ppm", ps1.begin(),
ps1.size());
//if (isDump) */DumbPPMPrint("c:\\case12_B.ppm", ps2.begin(),
ps2.size());
}
}
void DumbPPMPrint(char *name, std::vector<polygon_2d >::iterator it,
unsigned int n)
{
//WSQ Viewer can be of help
//http://www.cognaxon.com/index.php?page=wsqview
//the holes are black.
//the more number of polygons are present at a pixel the brighter
the pixel is.
unsigned int imgwidth = 256; //pixel width of image
unsigned int imgheight = 256; //pixel height of image
float width = 400.0; //width of image: 10 units (e.g.
meters)
float height = 400.0; //height of image: 10 units (e.g.
meters)
//header
FILE *signal = fopen(name, "wt");
fprintf(signal, "P3\n");
fprintf(signal, "# %s\n", name);
fprintf(signal, "%d %d\n", imgwidth, imgheight);
fprintf(signal, "255\n");
unsigned int x, y, i;
float xpos, ypos;
// PPM images carry red, green, blue color channels.
int val0, val1, val2, weight;
std::vector<polygon_2d >::iterator poly;
weight = 255/n;
if (weight < 101) weight = 101;
for (y = 0; y < imgheight; y++)
{
ypos = height/2 - height * y / imgheight;
for (x = 0; x < imgwidth; x++)
{
xpos = width/2 - width * x / imgwidth;
val0 = val1 = val2 = 0; //black
point_xy<float> point(xpos, ypos);
poly = it;
for (i = 0; i < n; i++, poly++)
{
if( within( point, (*poly) ) )
{
val0 += weight;
val1 += weight;
val2 += weight;
}
} //fi_poly
// clamp to allowed range
if (val0 < 0) val0 = 0; else if (val0 > 255) val0 = 255;
if (val1 < 0) val1 = 0; else if (val1 > 255) val1 = 255;
if (val2 < 0) val2 = 0; else if (val2 > 255) val2 = 255;
fprintf(signal, "%3d %3d %3d ", val0, val1, val2);
if (x%16 == 15) fprintf(signal, "\n");
} //fi_x
} //fi_y
fclose(signal);
}
//@_End_of_Code
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk