/*
* Copyright (c) 2007 Hypertriton, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_FREESG
#include
#include
#include
#include
#include
#include
#include "voxelpath.h"
/*
* Since our trajectory planning algorithm must be integer-only, we use
* the STEPLEN constant to adjust maximum travel vs. sub-step accuracy.
*/
#define STEPMAX (0xffffffff-1)
#define STEPLEN 204800
#define MAXSTEPS (STEPMAX/STEPLEN)
static int x1 = 10, y_1 = 10, z1 = 10;
static int x2 = 100, y2 = 70, z2 = 80;
/*
* Trace a linear path. We simply find the component with the largest
* difference and integrate the other components over it.
*/
void
VoxelLine(SG_Voxel *vol)
{
int dx, dy, dz;
int x, y, z;
int vx, vy, vz;
int xdir, ydir, zdir;
int step;
printf("Line: [%d,%d,%d] -> [%d,%d,%d]\n", x1, y_1, z1, x2, y2, z2);
dx = abs(x2 - x1);
dy = abs(y2 - y_1);
dz = abs(z2 - z1);
xdir = (x2 > x1) ? 1 : -1;
ydir = (y2 > y_1) ? 1 : -1;
zdir = (z2 > z1) ? 1 : -1;
printf("Delta = %d,%d,%d\n", dx, dy, dz);
printf("Dir = %d,%d,%d\n", xdir, ydir, zdir);
if (dx >= dy && dx >= dz) {
if (dx == 0) {
return;
}
dy = dy*STEPLEN/dx;
dz = dz*STEPLEN/dx;
dx *= STEPLEN;
for (x = 0, step = 0;
x < dx && step < MAXSTEPS;
x += STEPLEN, step++) {
y = dy*ydir*step;
z = dz*zdir*step;
SG_VoxelSet3(vol,
x1 + xdir*step,
y_1 + y/STEPLEN,
z1 + z/STEPLEN,
0.5);
}
} else if (dy >= dx && dy >= dz) {
if (dy == 0) {
return;
}
dx = dx*STEPLEN/dy;
dz = dz*STEPLEN/dy;
dy *= STEPLEN;
for (y = 0, step = 0;
y < dy && step < MAXSTEPS;
y += STEPLEN, step++) {
x = dx*xdir*step;
z = dz*zdir*step;
SG_VoxelSet3(vol,
x1 + x/STEPLEN,
y_1 + ydir*step,
z1 + z/STEPLEN,
0.5);
}
} else if (dz >= dx && dz >= dy) {
if (dz == 0) {
return;
}
dx = dx*STEPLEN/dz;
dy = dy*STEPLEN/dz;
dz *= STEPLEN;
for (z = 0, step = 0;
z < dz && step < MAXSTEPS;
z += STEPLEN, step++) {
x = dx*xdir*step;
y = dy*ydir*step;
SG_VoxelSet3(vol,
x1 + x/STEPLEN,
y_1 + y/STEPLEN,
z1 + zdir*step,
0.5);
}
}
}
/* Trace a circular path on a plane. */
static void
SG_VoxelCircle(SG_Voxel *vol, int wx, int wy, int wz, int radius)
{
int v = 2*radius - 1;
int e = 0, u = 1;
int x = 0, y = radius;
while (x < y) {
SG_VoxelSet3(vol, wx+x, wy+y, wz, 1.0);
SG_VoxelSet3(vol, wx+x, wy-y, wz, 1.0);
SG_VoxelSet3(vol, wx-x, wy+y, wz, 1.0);
SG_VoxelSet3(vol, wx-x, wy-y, wz, 1.0);
e += u;
u += 2;
if (v < 2*e) {
y--;
e -= v;
v -= 2;
}
x++;
SG_VoxelSet3(vol, wx+y, wy+x, wz, 1.0);
SG_VoxelSet3(vol, wx+y, wy-x, wz, 1.0);
SG_VoxelSet3(vol, wx-y, wy+x, wz, 1.0);
SG_VoxelSet3(vol, wx-y, wy-x, wz, 1.0);
}
SG_VoxelSet3(vol, wx-radius, wy, wz, 1.0);
SG_VoxelSet3(vol, wx+radius, wy, wz, 1.0);
}
static void
DoClearVoxel(AG_Event *event)
{
SG_Voxel *vol = AG_PTR(1);
SG_VoxelReset(vol, 0.0);
}
#if 0
static void
DoFillVoxel(AG_Event *event)
{
SG_Voxel *vol = AG_PTR(1);
SG_VoxelReset(vol, 1.0);
}
#endif
static void
DoTraceLine(AG_Event *event)
{
SG_Voxel *vol = AG_PTR(1);
SG_VoxelReset(vol, 0.0);
VoxelLine(vol);
}
void
VoxelPathDialog(SG_Voxel *vol)
{
AG_Window *win;
AG_Box *box;
AG_Numerical *nums[6];
win = AG_WindowNew(0);
AG_WindowSetCaptionS(win, "Voxel Operations");
AG_WindowSetPosition(win, AG_WINDOW_LOWER_LEFT, 0);
AG_ButtonNewFn(win, AG_BUTTON_HFILL, "Clear", DoClearVoxel, "%p", vol);
/*AG_ButtonNewFn(win, AG_BUTTON_HFILL, "Fill", DoFillVoxel, "%p", vol); */
box = AG_BoxNew(win, AG_BOX_VERT, AG_BOX_HFILL);
{
int i;
AG_LabelNewS(box, 0, "Line: ");
nums[0] = AG_NumericalNewInt(box, 0, NULL, "X1:", &x1);
nums[1] = AG_NumericalNewInt(box, 0, NULL, "Y1:", &y_1);
nums[2] = AG_NumericalNewInt(box, 0, NULL, "Z1:", &z1);
nums[3] = AG_NumericalNewInt(box, 0, NULL, "X2:", &x2);
nums[4] = AG_NumericalNewInt(box, 0, NULL, "Y2:", &y2);
nums[5] = AG_NumericalNewInt(box, 0, NULL, "Z2:", &z2);
for (i = 0; i < 6; i++) {
AG_SetEvent(nums[i], "numerical-changed",
DoTraceLine, "%p", vol);
}
AG_ButtonNewFn(box, AG_BUTTON_HFILL, "OK",
DoTraceLine, "%p", vol);
}
AG_WindowShow(win);
}
void
VoxelPathView(SG *sg, SG_Voxel *vol)
{
AG_Window *win;
win = AG_WindowNew(0);
AG_WindowSetCaptionS(win, "Trajectory");
SG_ViewNew(win, sg, SG_VIEW_EXPAND);
AG_WindowSetGeometryAlignedPct(win, AG_WINDOW_MC, 60, 40);
AG_WindowShow(win);
}
#endif /* HAVE_FREESG */