void AffineParts(void) { PARTTL *part = in_parts_hd; int px = 0, py = 0, pw = 0, ph = 0; while (NULL != part) { CalcView(part, &px, &py, &pw, &ph); AffinePart(part, pw, ph, 0); part = part->n; } }
void PutParts(void) { PARTTL *part = in_parts_hd; XSetForeground(display, gc, back); XFillRectangle(display, scratchmap, gc, 0, 0, WINW, WINH); if (NULL == part) return; while (NULL != part->n) part = part->n; while (NULL != part) { int px = 0, py = 0, pw = 0, ph = 0; CalcView(part, &px, &py, &pw, &ph); XSetForeground(display, gc, black); switch (part->stat) { case RAISED: XFillRectangle(display, scratchmap, gc, px - RWAKU - RUP, py - RWAKU - RUP, pw + RWAKU * 2, ph + RWAKU * 2); DrawShadow(scratchmap, px + 8 - 1 - RWAKU, py + 8 - 1 - RWAKU, pw + RWAKU * 2, ph + RWAKU * 2, 8 + RUP); PUTPART(px - RUP, py - RUP); break; case POINT: XFillRectangle(display, scratchmap, gc, px - PWAKU, py - PWAKU, pw + PWAKU * 2, ph + PWAKU * 2); DrawShadow(scratchmap, px + 8 - 1 - PWAKU, py + 8 - 1 - PWAKU, pw + PWAKU * 2, ph + PWAKU * 2, 8); PUTPART(px, py); break; default: XDrawRectangle(display, scratchmap, gc, px - 1, py - 1, pw + 2, ph + 2); DrawShadow(scratchmap, px + 8 - 1, py + 8 - 1, pw + 2, ph + 2, 8); PUTPART(px, py); break; } part = part->p; } XCopyArea(display, scratchmap, scratch, gc, 0, 0, WINW, WINH, 0, 0); }
void PointPart(int x, int y) { PARTTL *part = in_parts_hd; int px = 0, py = 0, pw = 0, ph = 0; while (NULL != part) { CalcView(part, &px, &py, &pw, &ph); if (x < px || px + pw < x || y < py || py + ph < y) { part->stat = NONE; part = part->n; continue; } part->stat = POINT; part->bx = x - px; part->by = y - py; part = part->n; break; } while (NULL != part) { part->stat = NONE; part = part->n; } }
/* Determines visibility for each cell in the first quadrant. * (including edges of quadrant). The possible blocking neighbor is on * the right side or at the right-below corner or below the cell. * Returns 0 if successful, 1 otherwise */ static int First( MAP_UINT1 *out, /* write-only output map */ int viewr, /* row of view point */ int viewc, /* column of view point */ const MAP_REAL8 *dem, /* dem map */ const MAP_UINT1 *points) /* points map */ { int r, c, i; UINT1 pntVal; /* value in points.map */ REAL8 viewHght, visPlane; REAL8 *lastRow, *currRow; /* vis. planes of last and * current row. */ PRECOND(dem->GetGetTest(dem) == GET_MV_TEST); PRECOND(points->GetGetTest(points) == GET_MV_TEST); PRECOND(out->GetGetTest(out) == GET_MV_TEST); PRECOND(dem->Get(&viewHght, viewr, viewc, dem)); /* allocate and initialize the vis. planes of last and * current row. */ lastRow = (REAL8 *)ChkMalloc(sizeof(REAL8) * (viewc + 1)); if(lastRow == NULL) return 1; currRow = (REAL8 *)ChkMalloc(sizeof(REAL8) * (viewc + 1)); if(currRow == NULL) { free(lastRow); return 1; } for(i = 0; i <= viewc ; i++) { currRow[i] = VISMIN; /* lowest value possible */ lastRow[i] = VISMIN; /* lowest value possible */ } visPlane = VISMIN; /* vis. plane of view point */ dem->Get(&viewHght, viewr, viewc, dem); /* viewpoint height */ /* start from view point to left-upper corner */ for(r = viewr; 0 <= r; r--) { for(c = viewc; 0 <= c; c--) { /* Calculate possible blocking neighbor & vis. plane */ int rNext, cNext; /* possible blocking neighbor */ REAL8 height1; if(c != viewc) { int rc = (r - viewr) / (c - viewc); if(rc < 0.5) { /* take neighbor on the right */ rNext = r; cNext = c + 1; visPlane = currRow[c + 1]; } if(rc > 2) { /* take neighbor below (r, c) */ rNext = r + 1; cNext = c; visPlane = lastRow[c]; } if(rc <= 2 && 0.5 <= rc) { /* take right-below corner neighbor */ rNext = r + 1; cNext = c + 1; visPlane = lastRow[c + 1]; } } else { /* rc would cause division by 0 */ if(viewr == r) { rNext = r; cNext = c; visPlane = VISMIN; } else { rNext = r + 1; cNext = c; visPlane = lastRow[c]; } } /* Calculate visibility of current cell */ if(dem->Get(&height1, r, c, dem) && (points->Get(&pntVal, r, c, points))) { CalcView(out, currRow, lastRow, dem, points, r, c, rNext, cNext, visPlane, viewr, viewc, height1); } else { out->PutMV(r, c, out); /* not able to peer through a MV */ currRow[c] = REAL8_MAX; } } /* This row is done, take next row */ for(i = 0; i <= viewc; i++) { /* last row := current row */ lastRow[i] = currRow[i]; currRow[i] = 0; /* initialize */ } } free(lastRow); /* deallocate */ free(currRow); /* deallocate */ return 0; }
static int Fourth( MAP_UINT1 *out, /* write-only output map */ int viewr, /* row of view point */ int viewc, /* column of view point */ const MAP_REAL8 *dem, /* dem map */ const MAP_UINT1 *points, /* points map */ int nrRows, /* nr rows */ int nrCols) /* nr columns */ { int r, c, i; UINT1 pntVal; REAL8 viewHght, visPlane; REAL8 *lastRow, *currRow; /* contains visibility planes of * last row c.q. current row */ PRECOND(dem->GetGetTest(dem) == GET_MV_TEST); PRECOND(points->GetGetTest(points) == GET_MV_TEST); PRECOND(out->GetGetTest(out) == GET_MV_TEST); PRECOND(dem->Get(&viewHght, viewr, viewc, dem)); /* allocate and initialize last and current row */ lastRow = (REAL8 *)ChkMalloc(sizeof(REAL8) * (nrCols)); if(lastRow == NULL) return 1; currRow = (REAL8 *)ChkMalloc(sizeof(REAL8) * (nrCols)); if(currRow == NULL) { free(lastRow); return 1; } for(i = 0; i < nrCols ; i++) { currRow[i] = VISMIN; /* lowest value possible */ lastRow[i] = VISMIN; /* lowest value possible */ } visPlane = VISMIN; dem->Get(&viewHght, viewr, viewc, dem); if(viewr == nrCols - 1) { free(currRow); free(lastRow); return 0; /* no fourth quadrant */ } if(viewc == nrRows - 1) { free(currRow); free(lastRow); return 0; /* no fourth quadrant */ } /* start from view point to right-below corner */ for(r = viewr; r < nrRows; r++) { for(c = viewc; c < nrCols; c++) { /* Calculate blocking neighbor & its visibility plane */ int rNext, cNext; /* possible blocking neigh. */ REAL8 height1; if(c != viewc) { int rc = (r - viewr) / (c - viewc); if(rc < 0.5) { /* take neighbor on the left */ rNext = r; cNext = c - 1; visPlane = currRow[c - 1]; } if(2 < rc) { /* take neighbor above (r, c) */ rNext = r - 1; cNext = c; visPlane = lastRow[c]; } if(0.5 <= rc && rc <= 2) { /* take left-above corner neighbor */ rNext = r - 1; cNext = c - 1; visPlane = lastRow[c - 1]; } } else { /* rc would cause division by 0 */ if(viewr == r) { rNext = r; cNext = c; visPlane = VISMIN; } else { rNext = r - 1; cNext = c; visPlane = lastRow[c]; } } /* Calculate visibility current cell */ if(dem->Get(&height1, r, c, dem) && (points->Get(&pntVal, r, c, points))) { CalcView(out, currRow, lastRow, dem, points, r, c, rNext, cNext, visPlane, viewr, viewc, height1); } else { out->PutMV(r, c, out); /* not able to peer through a MV */ currRow[c] = REAL8_MAX; } } /* this row is done, take next row */ for(i = 0; i < nrCols; i++) { /* last row := current row */ lastRow[i] = currRow[i]; /* next row */ currRow[i] = 0; } } free(lastRow); /* deallocate */ free(currRow); /* deallocate */ return 0; }
void MainLoop(void) { int px = 0, py = 0, sx = 9, sy = 9, w = 0, h = 0; int osx, osy, ow, oh; #define INPUT_TEXT_SIZE 16 PutParts(); while (1) { char string_length, input_text[INPUT_TEXT_SIZE]; XFlush(display); if (input.button[2]) { eye.x += (input.x - WINW / 2) / SCROLL_SPDIV; eye.y += (input.y - WINH / 2) / SCROLL_SPDIV; PutParts(); XSync(display, 0); if (0 == XEventsQueued(display, QueuedAfterReading)) continue; } while (XEventsQueued(display, QueuedAfterReading) > 0) { XNextEvent(display, &event); switch (event.type) { case Expose: XCopyArea(display, scratchmap, scratch, gc, 0, 0, WINW, WINH, 0, 0); break; case MappingNotify: XRefreshKeyboardMapping((XMappingEvent *)&event); break; case KeyPress: string_length = XLookupString((XKeyEvent *)&event, input_text, INPUT_TEXT_SIZE, &key, NULL); if (1 == string_length) { switch (input_text[0]) { case 'q': return; case 'u': eye.scale += 256; AffineParts(); break; case 'd': if (eye.scale > 256) eye.scale -= 256; AffineParts(); break; } PutParts(); } break; case MotionNotify: if (CompressMNEvent(&event)) { input.x = event.xmotion.x; input.y = event.xmotion.y; break; } if (scratch != event.xmotion.window) { int rx, ry, rw, rh; osx = sx; osy = sy; ow = w; oh = h; XCopyArea(display, rootmap, cutmap, gc, osx - 9, osy - 9, ow + 10, oh + 10, osx - 9, osy - 9); CutRectangle(px, py, event.xmotion.x, event.xmotion.y, &sx, &sy, &w, &h); XSetForeground(display, gc, black); if (CantCut(w, h)) { XDrawRectangle(display, cutmap, gc, sx - 1, sy - 1, w + 1, h + 1); XCopyArea(display, rootmap, cutmap, gc, sx, sy, w, h, sx, sy); } else { XDrawRectangle(display, cutmap, gc, sx - 9, sy - 9, w + 1, h + 1); DrawShadow(cutmap, sx, sy, w, h, 8); XCopyArea(display, rootmap, cutmap, gc, sx, sy, w, h, sx - 8, sy - 8); } MaxArea(&rx, &ry, &rw, &rh, sx - 9, sy - 9, w + 10, h + 10, osx - 9, osy - 9, ow + 10, oh + 10); XCopyArea(display, cutmap, cut, gc, rx, ry, rw, rh, rx, ry); } if (input.button[0] && NULL != in_parts_hd) { if (RAISED == in_parts_hd->stat) { CalcCoord(event.xmotion.x - in_parts_hd->bx, event.xmotion.y - in_parts_hd->by, in_parts_hd); PutParts(); } else { PointPart(event.xmotion.x, event.xmotion.y); PutParts(); } } else { PointPart(event.xmotion.x, event.xmotion.y); PutParts(); } break; case ButtonPress: input.button[event.xbutton.button - 1] = 1; if (1 == event.xbutton.button && scratch != event.xbutton.window) { px = event.xbutton.x; py = event.xbutton.y; CutMode(px, py); break; } if (1 == event.xbutton.button) { RaisePart(); PutParts(); break; } break; case ButtonRelease: input.button[event.xbutton.button - 1] = 0; sx = sy = 9; w = h = 0; if (1 == event.xbutton.button && scratch != event.xbutton.window) { int sx, sy, w, h; PARTTL *part; XDestroyWindow(display, cut); CutRectangle(px, py, event.xmotion.x, event.xmotion.y, &sx, &sy, &w, &h); if (!CantCut(w, h)) { if (NULL == out_parts_hd) { fputs("parts over flow.\n", stderr); exit(1); } part = out_parts_hd; out_parts_hd = out_parts_hd->n; part->p = NULL; part->n = in_parts_hd; if (NULL != in_parts_hd) { in_parts_hd->p = part; } in_parts_hd = part; part->stat = NONE; part->x = eye.x + rand() % (WINW / 2) - WINW / 2; part->y = eye.y + rand() % (WINH / 2) - WINH / 2; part->w = w; part->h = h; part->source = XCreatePixmap(display, root, w, h, depth); XCopyArea(display, rootmap, part->source, gc, sx, sy, w, h, 0, 0); { int px = 0, py = 0; int pw = 0, ph = 0; ; CalcView(part, &px, &py, &pw, &ph); AffinePart(part, pw, ph, 1); } PutParts(); } break; } break; } } } }