976{
977 int i = 0, j, k;
980 char *edges_in_arcs;
982 int current_arc = 1;
983 int num_edges;
984 int edge_type;
985 int start, end;
987
988 const unsigned int min_quad_edges = 2;
989
990
991 if ( ! points )
992 lwerror(
"pta_unstroke called with null pointarray");
993
994
996 return NULL;
997
998
1000 {
1001
1002 lwerror(
"pta_unstroke needs implementation for npoints < 4");
1003 }
1004
1005
1006 num_edges = points->
npoints - 1;
1007 edges_in_arcs =
lwalloc(num_edges + 1);
1008 memset(edges_in_arcs, 0, num_edges + 1);
1009
1010
1011
1012 while( i < num_edges-2 )
1013 {
1014 unsigned int arc_edges;
1015 double num_quadrants;
1016 double angle;
1017
1019
1023 memcpy(&first, &a1,
sizeof(
POINT4D));
1024
1025 for( j = i+3; j < num_edges+1; j++ )
1026 {
1029
1031 {
1032
1033 LWDEBUGF(4,
"pt_continues_arc #%d", current_arc);
1035 for ( k = j-1; k > j-4; k-- )
1036 edges_in_arcs[k] = current_arc;
1037 }
1038 else
1039 {
1040
1041 LWDEBUG(4,
"pt_continues_arc = false");
1042 current_arc++;
1043 break;
1044 }
1045
1046 memcpy(&a1, &a2,
sizeof(
POINT4D));
1047 memcpy(&a2, &a3,
sizeof(
POINT4D));
1048 memcpy(&a3, &b,
sizeof(
POINT4D));
1049 }
1050
1051 if ( found_arc )
1052 {
1053
1054
1055
1056
1057 arc_edges = j - 1 - i;
1058 LWDEBUGF(4,
"arc defined by %d edges found", arc_edges);
1059 if ( first.
x == b.
x && first.
y == b.
y ) {
1060 LWDEBUG(4,
"arc is a circle");
1061 num_quadrants = 4;
1062 }
1063 else {
1067 if ( p2_side >= 0 ) angle = -angle;
1068
1069 if ( angle < 0 ) angle = 2 * M_PI + angle;
1070 num_quadrants = ( 4 * angle ) / ( 2 * M_PI );
1071 LWDEBUGF(4,
"arc angle (%g %g, %g %g, %g %g) is %g (side is %d), quadrants:%g", first.
x, first.
y, center.
x, center.
y, b.
x, b.
y, angle, p2_side, num_quadrants);
1072 }
1073
1074 if ( arc_edges < min_quad_edges * num_quadrants ) {
1075 LWDEBUGF(4,
"Not enough edges for a %g quadrants arc, %g needed", num_quadrants, min_quad_edges * num_quadrants);
1076 for ( k = j-1; k >= i; k-- )
1077 edges_in_arcs[k] = 0;
1078 }
1079
1080 i = j-1;
1081 }
1082 else
1083 {
1084
1085 edges_in_arcs[i] = 0;
1086 i = i+1;
1087 }
1088 }
1089
1090#if POSTGIS_DEBUG_LEVEL > 3
1091 {
1092 char *edgestr =
lwalloc(num_edges+1);
1093 for ( i = 0; i < num_edges; i++ )
1094 {
1095 if ( edges_in_arcs[i] )
1096 edgestr[i] = 48 + edges_in_arcs[i];
1097 else
1098 edgestr[i] = '.';
1099 }
1100 edgestr[num_edges] = 0;
1101 LWDEBUGF(3,
"edge pattern %s", edgestr);
1103 }
1104#endif
1105
1106 start = 0;
1107 edge_type = edges_in_arcs[0];
1109 for( i = 1; i < num_edges; i++ )
1110 {
1111 if( edge_type != edges_in_arcs[i] )
1112 {
1113 end = i - 1;
1115 start = i;
1116 edge_type = edges_in_arcs[i];
1117 }
1118 }
1120
1121
1122 end = num_edges - 1;
1124
1125
1126 if ( outcol->
ngeoms == 1 )
1127 {
1130 return outgeom;
1131 }
1133}
void * lwalloc(size_t size)
void lwcollection_free(LWCOLLECTION *col)
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
#define LW_TRUE
Return types for functions with status returns.
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
int ptarray_has_z(const POINTARRAY *pa)
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
int ptarray_has_m(const POINTARRAY *pa)
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
static LWGEOM * geom_from_pa(const POINTARRAY *pa, int32_t srid, int is_arc, int start, int end)
static double lw_arc_angle(const POINT2D *a, const POINT2D *b, const POINT2D *c)
Return ABC angle in radians TODO: move to lwalgorithm.
static int pt_continues_arc(const POINT4D *a1, const POINT4D *a2, const POINT4D *a3, const POINT4D *b)
Returns LW_TRUE if b is on the arc formed by a1/a2/a3, but not within that portion already described ...