52 #include <grass/gstypes.h>
53 #include <grass/glocale.h>
59 #define DONT_INTERSECT 0
60 #define DO_INTERSECT 1
63 #define LERP(a,l,h) ((l)+(((h)-(l))*(a)))
64 #define EQUAL(a,b) (fabs((a)-(b))<EPSILON)
65 #define ISNODE(p,res) (fmod((double)p,(double)res)<EPSILON)
67 #define SAME_SIGNS( a, b ) \
68 ((a >= 0 && b >= 0) || (a < 0 && b < 0))
70 static int drape_line_init(
int,
int);
71 static Point3 *_gsdrape_get_segments(geosurf *,
float *,
float *,
int *);
72 static float dist_squared_2d(
float *,
float *);
78 static float EPSILON = 0.000001;
81 static Point3 *Vi, *Hi, *Di;
96 static int drape_line_init(
int rows,
int cols)
99 if (
NULL == (I3d = (Point3 *) calloc(2 * (rows + cols),
sizeof(Point3)))) {
103 if (
NULL == (Vi = (Point3 *) calloc(cols,
sizeof(Point3)))) {
109 if (
NULL == (Hi = (Point3 *) calloc(rows,
sizeof(Point3)))) {
116 if (
NULL == (Di = (Point3 *) calloc(rows + cols,
sizeof(Point3)))) {
137 static Point3 *_gsdrape_get_segments(geosurf * gs,
float *bgn,
float *end,
142 float dir[2], yres, xres;
158 if (!((end[Y] - bgn[Y]) / (end[X] - bgn[X]) == yres / xres)) {
167 G_debug(5,
"_gsdrape_get_segments vi=%d, hi=%d, di=%d, num=%d",
181 static float dist_squared_2d(
float *p1,
float *p2)
188 return (dx * dx + dy * dy);
201 static int first = 1;
206 if (0 > drape_line_init(gs->rows, gs->cols)) {
207 G_warning(_(
"Unable to process vector map - out of memory"));
235 float *replace, xl, yb, xr, yt, xi, yi;
259 (bgn[X], bgn[Y], end[X], end[Y], xl, yb, xl, yt, &xi, &yi)) {
263 (bgn[X], bgn[Y], end[X], end[Y], xr, yb, xr, yt, &xi, &yi)) {
267 (bgn[X], bgn[Y], end[X], end[Y], xl, yb, xr, yb, &xi, &yi)) {
271 (bgn[X], bgn[Y], end[X], end[Y], xl, yt, xr, yt, &xi, &yi)) {
280 float pt1[2], pt2[2];
284 (bgn[X], bgn[Y], end[X], end[Y], xl, yb, xl, yt, &xi, &yi)) {
292 (bgn[X], bgn[Y], end[X], end[Y], xr, yb, xr, yt, &xi, &yi)) {
301 (bgn[X], bgn[Y], end[X], end[Y], xl, yb, xr, yb, &xi, &yi)) {
311 (bgn[X], bgn[Y], end[X], end[Y], xl, yt, xr, yt, &xi, &yi)) {
364 I3d[0][Z] = gs->att[ATT_TOPO].constant;
367 I3d[1][Z] = gs->att[ATT_TOPO].constant;
373 if (bgn[X] == end[X] && bgn[Y] == end[Y]) {
387 return (_gsdrape_get_segments(gs, bgn, end, num));
411 if (bgn[X] == end[X] && bgn[Y] == end[Y]) {
429 return (_gsdrape_get_segments(gs, bgn, end, num));
451 f[Z] = l[Z] = gs->att[ATT_TOPO].constant;
511 int offset, drow, dcol, vrow, vcol;
524 if (pt[X] < 0.0 || pt[Y] > ymax) {
529 if (pt[Y] < ymin || pt[X] > xmax) {
535 pt[Z] = gs->att[ATT_TOPO].constant;
548 if (pt[X] > 0.0 && pt[Y] < ymax) {
554 offset =
DRC2OFF(gs, drow, dcol);
561 offset =
DRC2OFF(gs, drow, dcol);
564 if ((pt[X] - p2[X]) /
VXRES(gs) > (pt[Y] - p2[Y]) /
VYRES(gs)) {
570 offset =
DRC2OFF(gs, drow, dcol);
579 offset =
DRC2OFF(gs, drow, dcol);
585 else if (pt[X] == 0.0) {
598 pt[Z] =
LERP(alpha, p1[Z], p2[Z]);
607 else if (pt[Y] == gs->yrange) {
617 pt[Z] =
LERP(alpha, p1[Z], p2[Z]);
622 else if (vrow ==
VROWS(gs)) {
626 if (pt[X] > 0.0 && pt[X] < xmax) {
630 offset =
DRC2OFF(gs, drow, dcol);
634 offset =
DRC2OFF(gs, drow, dcol);
638 pt[Z] =
LERP(alpha, p1[Z], p2[Z]);
642 else if (pt[X] == 0.0) {
652 offset =
DRC2OFF(gs, drow, dcol);
665 offset =
DRC2OFF(gs, drow, dcol);
669 offset =
DRC2OFF(gs, drow, dcol);
673 pt[Z] =
LERP(alpha, p1[Z], p2[Z]);
698 if (pt[X] >= 0.0 && pt[Y] <= gs->yrange) {
732 int num, i, found, cv, ch, cd, cnum;
733 float dv, dh, dd, big, cpoint[2];
735 cv = ch = cd = cnum = 0;
738 cpoint[
X] = first[
X];
739 cpoint[
Y] = first[
Y];
742 I3d[cnum][
X] = first[
X];
743 I3d[cnum][
Y] = first[
Y];
744 I3d[cnum][Z] = first[Z];
749 big = gs->yrange * gs->yrange + gs->xrange * gs->xrange;
752 for (i = 0; i <
num; i = cv + ch + cd) {
754 dv = dist_squared_2d(Vi[cv], cpoint);
766 dh = dist_squared_2d(Hi[ch], cpoint);
778 dd = dist_squared_2d(Di[cd], cpoint);
792 if (dd <= dv && dd <= dh) {
794 cpoint[
X] = I3d[cnum][
X] = Di[cd][
X];
795 cpoint[
Y] = I3d[cnum][
Y] = Di[cd][
Y];
796 I3d[cnum][Z] = Di[cd][Z];
815 cpoint[
X] = I3d[cnum][
X] = Vi[cv][
X];
816 cpoint[
Y] = I3d[cnum][
Y] = Vi[cv][
Y];
817 I3d[cnum][Z] = Vi[cv][Z];
831 cpoint[
X] = I3d[cnum][
X] = Hi[ch][
X];
832 cpoint[
Y] = I3d[cnum][
Y] = Hi[ch][
Y];
833 I3d[cnum][Z] = Hi[ch][Z];
839 if (i == cv + ch + cd) {
840 G_debug(5,
"order_intersects(): stuck on %d", cnum);
841 G_debug(5,
"order_intersects(): cv = %d, ch = %d, cd = %d", cv,
843 G_debug(5,
"order_intersects(): dv = %f, dh = %f, dd = %f", dv,
850 if (
EQUAL(last[X], cpoint[X]) &&
EQUAL(last[Y], cpoint[Y])) {
856 I3d[cnum][
X] = last[
X];
857 I3d[cnum][
Y] = last[
Y];
858 I3d[cnum][Z] = last[Z];
884 int fcol, lcol, incr, hits,
num, offset, drow1, drow2;
885 float xl, yb, xr, yt, z1, z2, alpha;
886 float xres, yres, xi, yi;
887 int bgncol, endcol,
cols, rows;
894 bgncol =
X2VCOL(gs, bgn[X]);
895 endcol =
X2VCOL(gs, end[X]);
897 if (bgncol > cols && endcol > cols) {
901 if (bgncol == endcol) {
905 fcol = dir[
X] > 0 ? bgncol + 1 : bgncol;
906 lcol = dir[
X] > 0 ? endcol : endcol + 1;
909 incr = lcol - fcol > 0 ? 1 : -1;
911 while (fcol > cols || fcol < 0) {
915 while (lcol > cols || lcol < 0) {
919 num = abs(lcol - fcol) + 1;
921 yb = gs->yrange - (yres * rows) -
EPSILON;
924 for (hits = 0; hits <
num; hits++) {
925 xl = xr =
VCOL2X(gs, fcol);
927 if (
segs_intersect(bgn[X], bgn[Y], end[X], end[Y], xl, yt, xr, yb,
934 Vi[hits][Z] = gs->att[ATT_TOPO].constant;
937 drow1 =
Y2VROW(gs, Vi[hits][Y]) * gs->y_mod;
938 drow2 = (1 +
Y2VROW(gs, Vi[hits][Y])) * gs->y_mod;
940 if (drow2 >= gs->rows) {
941 drow2 = gs->rows - 1;
945 ((gs->yrange - drow1 * gs->yres) - Vi[hits][Y]) / yres;
947 offset =
DRC2OFF(gs, drow1, fcol * gs->x_mod);
949 offset =
DRC2OFF(gs, drow2, fcol * gs->x_mod);
951 Vi[hits][Z] =
LERP(alpha, z1, z2);
980 int frow, lrow, incr, hits,
num, offset, dcol1, dcol2;
981 float xl, yb, xr, yt, z1, z2, alpha;
982 float xres, yres, xi, yi;
983 int bgnrow, endrow, rows,
cols;
990 bgnrow =
Y2VROW(gs, bgn[Y]);
991 endrow =
Y2VROW(gs, end[Y]);
992 if (bgnrow == endrow) {
996 if (bgnrow > rows && endrow > rows) {
1000 frow = dir[
Y] > 0 ? bgnrow : bgnrow + 1;
1001 lrow = dir[
Y] > 0 ? endrow + 1 : endrow;
1004 incr = lrow - frow > 0 ? 1 : -1;
1006 while (frow > rows || frow < 0) {
1010 while (lrow > rows || lrow < 0) {
1014 num = abs(lrow - frow) + 1;
1019 for (hits = 0; hits <
num; hits++) {
1020 yb = yt =
VROW2Y(gs, frow);
1022 if (
segs_intersect(bgn[X], bgn[Y], end[X], end[Y], xl, yt, xr, yb,
1029 Hi[hits][Z] = gs->att[ATT_TOPO].constant;
1032 dcol1 =
X2VCOL(gs, Hi[hits][X]) * gs->x_mod;
1033 dcol2 = (1 +
X2VCOL(gs, Hi[hits][X])) * gs->x_mod;
1035 if (dcol2 >= gs->cols) {
1036 dcol2 = gs->cols - 1;
1039 alpha = (Hi[hits][
X] - (dcol1 * gs->xres)) / xres;
1041 offset =
DRC2OFF(gs, frow * gs->y_mod, dcol1);
1043 offset =
DRC2OFF(gs, frow * gs->y_mod, dcol2);
1045 Hi[hits][Z] =
LERP(alpha, z1, z2);
1076 int fdig, ldig, incr, hits,
num, offset;
1077 int vrow, vcol, drow1, drow2, dcol1, dcol2;
1078 float xl, yb, xr, yt, z1, z2, alpha;
1079 float xres, yres, xi, yi, dx, dy;
1080 int diags,
cols, rows, lower;
1087 diags = rows +
cols;
1090 vrow =
Y2VROW(gs, end[Y]);
1091 vcol =
X2VCOL(gs, end[X]);
1094 lower = ((end[
X] - pt[
X]) / xres > (end[Y] - pt[Y]) / yres);
1095 ldig = lower ? vrow + vcol + 1 : vrow + vcol;
1098 vrow =
Y2VROW(gs, bgn[Y]);
1099 vcol =
X2VCOL(gs, bgn[X]);
1102 lower = ((bgn[
X] - pt[
X]) / xres > (bgn[Y] - pt[Y]) / yres);
1103 fdig = lower ? vrow + vcol + 1 : vrow + vcol;
1114 incr = ldig - fdig > 0 ? 1 : -1;
1116 while (fdig > diags || fdig < 0) {
1120 while (ldig > diags || ldig < 0) {
1124 num = abs(ldig - fdig) + 1;
1126 for (hits = 0; hits <
num; hits++) {
1127 yb = gs->yrange - (yres * (fdig < rows ? fdig : rows)) -
EPSILON;
1129 yt = gs->yrange - (yres * (fdig < cols ? 0 : fdig -
cols)) +
EPSILON;
1132 if (
segs_intersect(bgn[X], bgn[Y], end[X], end[Y], xl, yb, xr, yt,
1145 drow1 =
Y2VROW(gs, Di[hits][Y]) * gs->y_mod;
1146 drow2 = (1 +
Y2VROW(gs, Di[hits][Y])) * gs->y_mod;
1148 if (drow2 >= gs->rows) {
1149 drow2 = gs->rows - 1;
1154 Di[hits][Z] = gs->att[ATT_TOPO].constant;
1157 dcol1 =
X2VCOL(gs, Di[hits][X]) * gs->x_mod;
1158 dcol2 = (1 +
X2VCOL(gs, Di[hits][X])) * gs->x_mod;
1160 if (dcol2 >= gs->cols) {
1161 dcol2 = gs->cols - 1;
1164 dx =
DCOL2X(gs, dcol2) - Di[hits][
X];
1165 dy =
DROW2Y(gs, drow1) - Di[hits][
Y];
1167 sqrt(dx * dx + dy * dy) / sqrt(xres * xres + yres * yres);
1169 offset =
DRC2OFF(gs, drow1, dcol2);
1171 offset =
DRC2OFF(gs, drow2, dcol1);
1173 Di[hits][Z] =
LERP(alpha, z1, z2);
1211 float x4,
float y4,
float *x,
float *
y)
1213 float a1, a2, b1, b2, c1, c2;
1214 float r1, r2, r3, r4;
1215 float denom, offset,
num;
1222 c1 = x2 * y1 - x1 * y2;
1226 r3 = a1 * x3 + b1 * y3 + c1;
1227 r4 = a1 * x4 + b1 * y4 + c1;
1240 c2 = x4 * y3 - x3 * y4;
1243 r1 = a2 * x1 + b2 * y1 + c2;
1244 r2 = a2 * x2 + b2 * y2 + c2;
1257 denom = a1 * b2 - a2 * b1;
1263 offset = denom < 0 ? -denom / 2 : denom / 2;
1269 num = b1 * c2 - b2 * c1;
1273 num = a2 * c1 - a1 * c2;
1322 intersect[Z] = (plane[
X] * x + plane[
Y] * y + plane[W]) / -plane[Z];
1337 Point3 v1, v2, norm;
1339 v1[
X] = p1[
X] - p3[
X];
1340 v1[
Y] = p1[
Y] - p3[
Y];
1341 v1[Z] = p1[Z] - p3[Z];
1343 v2[
X] = p2[
X] - p3[
X];
1344 v2[
Y] = p2[
Y] - p3[
Y];
1345 v2[Z] = p2[Z] - p3[Z];
1352 plane[W] = -p3[
X] * norm[
X] - p3[
Y] * norm[
Y] - p3[Z] * norm[Z];
1367 c[
X] = (a[
Y] * b[Z]) - (a[Z] * b[Y]);
1368 c[
Y] = (a[Z] * b[
X]) - (a[X] * b[Z]);
1369 c[Z] = (a[
X] * b[
Y]) - (a[Y] * b[X]);
void G_free(void *buf)
Free allocated memory.
#define DRC2OFF(gs, drow, dcol)
int XY_intersect_plane(float *intersect, float *plane)
Check for intersection (point and plane)
int in_vregion(geosurf *gs, float *pt)
ADD.
int gsdrape_set_surface(geosurf *gs)
ADD.
void interp_first_last(geosurf *gs, float *bgn, float *end, Point3 f, Point3 l)
ADD.
int gs_point_is_masked(geosurf *gs, float *pt)
Check if point is masked.
int get_diag_intersects(geosurf *gs, float *bgn, float *end, float *dir)
Get diagonal intersects.
int viewcell_tri_interp(geosurf *gs, typbuff *buf, Point3 pt, int check_mask)
ADD.
int seg_intersect_vregion(geosurf *gs, float *bgn, float *end)
Check if segment intersect vector region.
int get_vert_intersects(geosurf *gs, float *bgn, float *end, float *dir)
ADD.
void GS_v2dir(float *v1, float *v2, float *v3)
Get a normalized direction from v1 to v2, store in v3 (2D)
typbuff * gs_get_att_typbuff(geosurf *gs, int desc, int to_write)
Get attribute data buffer.
Point3 * gsdrape_get_allsegments(geosurf *gs, float *bgn, float *end, int *num)
Get all segments.
int get_horz_intersects(geosurf *gs, float *bgn, float *end, float *dir)
Get horizontal intersects.
int Point_on_plane(Point3 p1, Point3 p2, Point3 p3, Point3 unk)
Check if point is on plane.
int _viewcell_tri_interp(geosurf *gs, Point3 pt)
ADD.
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
int P3toPlane(Point3 p1, Point3 p2, Point3 p3, float *plane)
Define plane.
Point3 * gsdrape_get_segments(geosurf *gs, float *bgn, float *end, int *num)
ADD.
void GS_v3eq(float *v1, float *v2)
Copy vector values.
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
int G_debug(int level, const char *msg,...)
Print debugging message.
int gs_get_att_src(geosurf *gs, int desc)
Get attribute source.
#define VCOL2DCOL(gs, vcol)
int order_intersects(geosurf *gs, Point3 first, Point3 last, int vi, int hi, int di)
ADD.
float GS_P2distance(float *from, float *to)
Calculate distance in plane.
#define VROW2DROW(gs, vrow)
int V3Cross(Point3 a, Point3 b, Point3 c)
Get cross product.
int segs_intersect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float *x, float *y)
Line intersect.
#define GET_MAPATT(buff, offset, att)