home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * FILE: linecalc.c
- * DESC: These routines include the warping calculations and
- * the line-handling functions.
- *
- * HISTORY: Created 3/11/1993
- * LAST CHANGED: 5/ 6/1993
- *
- * Copyright (c) 1993 by Scott Anderson
- *
- ****************************************************************/
-
- /* ----------------------INCLUDES----------------------------- */
-
- #include <conio.h>
- #include <stdio.h>
- #include <io.h>
- #include <math.h>
- #include <graph.h>
-
- #include <malloc.h>
- #include <memory.h>
- #include <string.h>
-
- #include "define.h"
-
- /* -----------------------MACROS------------------------------ */
-
- #define PIXEL(p,x,y) (p->pixmap[y * (long) p->wide + x])
- #define SQUARE(x) (((long) x)*(x))
-
- /* ----------------------PROTOTYPES--------------------------- */
-
- /**** line routines ****/
- int xorLine(int x1, int y1, int x2, int y2);
- int getLine(int *argx1, int *argy1, int *argx2, int *argy2);
- int findPoint(LINE_LIST *lineList, int * line, int * point,
- int x, int y);
- int movePoint();
-
- /**** warping and morphing routines ****/
- int sumLines(PICTURE *picture, COLOR *color, LINE *origline,
- POINT *warp, LINE *warpline);
- float getSourceLoc(POINT *orig, LINE *origline, POINT *warp,
- LINE *warpline);
- int setLength(LINE *line);
-
- void setupScreen(PICTURE *pic, int editFlag);
-
- /* ----------------------EXTERNALS---------------------------- */
-
- /* set from last picture loaded */
- extern int Xmin, Ymin, Xmax, Ymax;
-
- extern int NumLines;
-
- extern LINE SrcLine[MAX_LINES];
- extern LINE DstLine[MAX_LINES];
-
- /* ----------------------GLOBAL DATA-------------------------- */
-
- int TargFlag=0;
-
- /******** These are the basic warping calculations **********/
-
- /*****************************************************************
- * FUNC: int sumLines(PICTURE *picture, COLOR *color,
- * LINE *origline, POINT *warp, LINE *warpline)
- *
- * DESC: Sum and weight the contribution of each warping line
- *****************************************************************/
-
- int
- sumLines(PICTURE *picture, COLOR *color, LINE *origline,
- POINT *warp, LINE *warpline)
- {
- int x, y;
- float weight, weightSum;
- float distance;
- int line;
- POINT orig;
- int paletteIndex;
- float deltaSumX = 0.0;
- float deltaSumY = 0.0;
-
- /* if no control lines, get an unwarped pixel */
- if (NumLines == 0)
- orig = *warp;
- else {
- weightSum = 0.0;
- for (line = 0; line < NumLines; line++,
- origline++, warpline++) {
- distance = getSourceLoc(&orig,origline,warp,warpline);
- weight = 1/(.001+distance*distance);
- deltaSumX += (orig.x - warp->x) * weight;
- deltaSumY += (orig.y - warp->y) * weight;
- weightSum += weight;
- }
- orig.x = warp->x + deltaSumX / weightSum + .5;
- orig.y = warp->y + deltaSumY / weightSum + .5;
- }
-
- /* clip it to the nearest border pixel */
- x = clip(orig.x, Xmin, Xmax);
- y = clip(orig.y, Ymin, Ymax);
- paletteIndex = PIXEL (picture, x, y);
- color->r = picture->pal.c[paletteIndex].r;
- color->g = picture->pal.c[paletteIndex].g;
- color->b = picture->pal.c[paletteIndex].b;
- return (paletteIndex);
- }
-
- /*****************************************************************
- * FUNC: float getSourceLoc(POINT *orig, LINE *origline,
- * POINT *warp, LINE *warpline)
- *
- * DESC: For a given line, locate the corresponding warped pixel
- *****************************************************************/
-
- float
- getSourceLoc(POINT *orig, LINE *origline, POINT *warp,
- LINE *warpline)
- {
- float fraction, fdist;
- int dx, dy;
- float distance;
-
- dx = warp->x - warpline->p[0].x;
- dy = warp->y - warpline->p[0].y;
- fraction = (dx * (long) warpline->delta_x + dy
- * (long) warpline->delta_y)
- / (float) (warpline->length_square);
- fdist = (dx * (long) -warpline->delta_y + dy
- * (long) warpline->delta_x)
- / (float) warpline->length;
- if (fraction <= 0 )
- distance = sqrt(dx*(long) dx + dy * (long) dy);
- else if (fraction >= 1) {
- dx = warp->x - warpline->p[1].x;
- dy = warp->y - warpline->p[1].y;
- distance = sqrt(dx*(long) dx + dy * (long) dy);
- }
- else if (fdist >= 0)
- distance = fdist;
- else
- distance = -fdist;
- orig->x = origline->p[0].x + fraction * origline->delta_x -
- fdist * origline->delta_y
- / (float) origline->length + .5;
- orig->y = origline->p[0].y + fraction * origline->delta_y +
- fdist * origline->delta_x
- / (float) origline->length + .5;
- return distance;
- }
-
- /*****************************************************************
- * FUNC: int setLength(LINE *line)
- *
- * DESC: Set the deltas, the length and the length squared
- * for a given line.
- *****************************************************************/
-
- int
- setLength (LINE *line)
- {
- line->delta_x = line->p[1].x - line->p[0].x;
- line->delta_y = line->p[1].y - line->p[0].y;
- line->length_square = SQUARE(line->delta_x)
- + SQUARE(line->delta_y);
- line->length = sqrt(line->length_square);
- }
-
- /********************* The line routines **********************/
-
- /*****************************************************************
- * FUNC: int xorLine(int x1, int y1, int x2, int y2)
- *
- * DESC: Draw a line on the screen using the XOR of the
- * screen index.
- *****************************************************************/
-
- int
- xorLine(int x1, int y1, int x2, int y2)
- {
- int oldcolor = _getcolor();
-
- _setcolor(WHITE); /* Use white as the xor color */
- _setwritemode(_GXOR);
- _moveto (x1,y1);
- _lineto (x2,y2);
- _setcolor(oldcolor); /* restore the old color */
- }
-
- /*****************************************************************
- * FUNC: int getLine(int *argx1, int *argy1, int *argx2, int*argy2)
- *
- * DESC: Input a line on the screen with the mouse.
- *****************************************************************/
-
- int
- getLine (int *argx1, int *argy1, int *argx2, int *argy2)
- {
- int x1,y1, x2,y2;
- int oldx, oldy;
- int input;
-
- /* save the current mode */
- short old_mode = _getwritemode();
-
- /* get input until we have a real line, not just a point */
- do {
- /* wait for button or key press */
- while (!(input = mousePos (&x1, &y1)));
- if (input & KEYPRESS) {
- _setwritemode(old_mode);
- return 1;
- }
- oldx=x1, oldy=y1;
- hideMouse();
- /* prime the pump with this dot */
- xorLine (x1, y1, oldx, oldy);
- showMouse();
- while (input = mousePos (&x2, &y2)) {
- /* rubber band a line while the mouse is dragged */
- if (x2 != oldx || y2 != oldy)
- {
- hideMouse();
- xorLine (x1, y1, oldx, oldy);
- xorLine (x1, y1, x2, y2);
- showMouse();
- oldx=x2, oldy=y2;
- }
- }
- } while (x1 == x2 && y1 == y2);
-
- *argx1 = x1, *argy1 = y1;
- *argx2 = x2, *argy2 = y2;
-
- _setwritemode(old_mode); /* get out of XOR mode */
- return (0);
- }
-
- /*****************************************************************
- * FUNC: int findPoint(LINE_LIST *lineList, int * line,
- * int * point, int x, int y)
- *
- * DESC: loop thru dstline and find point within GRAB_DISTANCE,
- * return 1 if found, 0 otherwise.
- *****************************************************************/
-
- int
- findPoint (LINE_LIST *lineList, int * line, int * point,
- int x, int y)
- {
- int l, p;
- int minl, minp;
- long length;
- long minlength = SQUARE(640) + SQUARE(480);
-
- for (l = 0; l < lineList->number; l++) {
- for (p = 0; p <= 1; p++) {
- length = SQUARE(lineList->line[l].p[p].x - x)
- + SQUARE(lineList->line[l].p[p].y - y);
- if (length < minlength) {
- minlength = length;
- minl = l;
- minp = p;
- }
- }
- }
- if (minlength > GRAB_DISTANCE)
- return 0;
- *line = minl;
- *point = minp;
- return 1;
- }
-
- /*****************************************************************
- * FUNC: int movePoint(LINE_LIST *lineList)
- *
- * DESC: Grab a point and move it. Return 1 when key is pressed,
- * else return 0.
- *****************************************************************/
-
- int
- movePoint(LINE_LIST *lineList)
- {
- int stuckx, stucky, movex,movey;
- int oldx, oldy;
- int input;
- int line, point;
-
- /* save the current mode */
- short old_mode = _getwritemode();
-
- do {
- /* keep getting input until we have a mouse button */
- while (!(input = mousePos (&movex, &movey)));
- if (input & KEYPRESS) {
- _setwritemode(old_mode);
- return 1;
- }
- if (!findPoint(lineList, &line, &point, movex, movey)) {
- _setwritemode(old_mode);
- return 0;
- }
-
- /* establish fixed end point */
- stuckx = lineList->line[line].p[1-point].x;
- stucky = lineList->line[line].p[1-point].y;
-
- oldx=movex, oldy=movey;
- hideMouse();
- /* erase the old line */
- xorLine (stuckx,
- stucky,
- lineList->line[line].p[point].x,
- lineList->line[line].p[point].y);
- /* and prime the pump with the new line */
- xorLine (stuckx, stucky, oldx, oldy);
- showMouse();
-
- while (input = mousePos (&movex, &movey)) {
- /* rubber band a line while the mouse is dragged */
- if (movex != oldx || movey != oldy) {
- hideMouse();
- xorLine (stuckx, stucky, oldx, oldy);
- xorLine (stuckx, stucky, movex, movey);
- showMouse();
- oldx=movex, oldy=movey;
- }
- }
- } while (stuckx == movex && stucky == movey);
-
- lineList->line[line].p[point].x = movex;
- lineList->line[line].p[point].y = movey;
-
- _setwritemode(old_mode); /* get out of XOR mode */
- return (0);
- }
-
- /*****************************************************************
- * FUNC: void createLines(PICTURE *pic, LINE_LIST *lineList)
- *
- * DESC: create a list of line segments for a picture
- *****************************************************************/
-
- void
- createLines(PICTURE *pic, LINE_LIST *lineList)
- {
- setupScreen(pic, 0); /* set for enter prompt */
-
- initMouse();
- showMouse();
- for (lineList->number = 0;lineList->number < MAX_LINES;
- lineList->number++) {
- if (getLine(&lineList->line[lineList->number].p[0].x,
- &lineList->line[lineList->number].p[0].y,
- &lineList->line[lineList->number].p[1].x,
- &lineList->line[lineList->number].p[1].y))
- break;
- }
- hideMouse();
- }
-
-
- /*****************************************************************
- * FUNC: void editLines(PICTURE *pic, LINE_LIST *lineList)
- *
- * DESC: move around some existing lines
- *****************************************************************/
-
- void
- editLines(PICTURE *pic, LINE_LIST *lineList)
- {
- int segment;
-
- setupScreen(pic, 1); /* set for edit prompt */
-
- initMouse();
- for (segment = 0; segment < lineList->number; segment++) {
- xorLine(lineList->line[segment].p[0].x,
- lineList->line[segment].p[0].y,
- lineList->line[segment].p[1].x,
- lineList->line[segment].p[1].y);
- }
- showMouse();
- /* move the endpoints around */
- while(!movePoint(lineList));
- hideMouse();
- }
-
- /*****************************************************************
- * FUNC: void setupScreen(PICTURE *pic, int editFlag)
- *
- * DESC: Print a message introducing the screen, wait for input,
- * then set the graphics mode and display the screen.
- *****************************************************************/
-
- void
- setupScreen(PICTURE *pic, int editFlag)
- {
- static char *editMess[2] = {"enter", "edit"};
- static char *targMess[2] = {"source", "target"};
- setTextMode();
-
- _settextposition(VTAB, HTAB);
- printf("When you are ready to %s the control lines",
- editMess[editFlag]);
- _settextposition(VTAB+2, HTAB);
- printf("for the %s image, press any key.",
- targMess[TargFlag]);
- waitForKey();
-
- setGraphicsMode();
- displayPicture(pic);
- }
-
-