Exemplo n.º 1
0
void ViewPort::ShiftView( int x, int y, double pixel_size, double offset_x, double offset_y, bool use_proxy )
{
	RECT rx, ry;
	HCURSOR cur;

	if ( view->bmi && viewDC )
		{
		cur = SetCursor( LoadCursor( 0, IDC_WAIT ) );				// show hourglass, this could be slow
		view->Shift( x, -y );										// view y is opposite from screen
		if ( x != 0 )
			{
			if ( x < 0 ) { rx.left = width+x; rx.right = width-1; }
				  else	{ rx.left = 0; rx.right = x; }
			rx.top = 0; rx.bottom = height-1;
			RenderImages( rx, pixel_size, offset_x, offset_y, use_proxy );	// render empty side rectangle
			}
		if ( y != 0 )
			{
			if ( -y < 0 ) { ry.top = height-y; ry.bottom = height-1; }
				  else { ry.top = 0; ry.bottom = -y; }
			ry.left = 0; ry.right = width-1;
			RenderImages( ry, pixel_size, offset_x, offset_y, use_proxy );	// empty top/bottom rectangle
			}
		ImageToViewDC();											// blt to DC
		DrawContours( pixel_size, offset_x, offset_y );			// draw contours
		DrawActiveDomain( pixel_size, offset_x, offset_y );		// or domain boundary if this is domain view
		DrawEditContour( pixel_size, offset_x, offset_y );		// finally render the contour being created
		SetCursor( cur );											// restore cursor
		needsRendering = false;			// still need an Invalidation of window to display viewDC
		}
}
Exemplo n.º 2
0
bool ViewPort::Regenerate( RECT region, double pixel_size, double offset_x, double offset_y, bool use_proxy )
{
	HCURSOR cur;
	bool wasregenerated = false;

	if ( view->bmi && viewDC )
		{
		if ( needsRendering )										// render the domains
			{
			cur = SetCursor( LoadCursor( 0, IDC_WAIT ) );			// show hourglass, this could be slow
			RenderImages( region, pixel_size, offset_x, offset_y, use_proxy );	// render images
			SetCursor( cur );										// restore cursor
			}
		if ( needsRendering || needsDrawing )						// if images were rendered, redraw traces
			{
			ImageToViewDC();										// blt to DC
			DrawContours( pixel_size, offset_x, offset_y );			// draw contours
			DrawActiveDomain( pixel_size, offset_x, offset_y );		// or domain boundary if this is domain view
			DrawEditContour( pixel_size, offset_x, offset_y );		// finally render the contour being created
			}
		wasregenerated = needsRendering || needsDrawing;			// report whether changes were made
		needsRendering = false;
		needsDrawing = false;										// view bitmap is up to date -- can display it
		}

	return( wasregenerated );
}
Exemplo n.º 3
0
void ShowScene2(int mode, int view_mode, int quad, GLint s_left, GLint s_down){

  if(rotation_type==EYE_CENTERED&&nskyboxinfo>0)draw_skybox();

  if(UpdateLIGHTS==1)updateLights(light_position0,light_position1);

  if(mode==DRAWSCENE){
    glPointSize((float)1.0);


    /* ++++++++++++++++++++++++ draw trees +++++++++++++++++++++++++ */

    if(ntreeinfo>0){
      CLIP_GEOMETRY;
      drawtrees();
      SNIFF_ERRORS("after drawtrees");
    }

/* ++++++++++++++++++++++++ draw particles +++++++++++++++++++++++++ */

    if(showsmoke==1){
      CLIP_VALS;
      drawpart_frame();
    }

/* ++++++++++++++++++++++++ draw evacuation +++++++++++++++++++++++++ */

    if(showevac==1){
      CLIP_VALS;
      drawevac_frame();
    }

/* ++++++++++++++++++++++++ draw targets +++++++++++++++++++++++++ */

    if(showtarget==1){
      CLIP_VALS;
      drawTargets();
    }

#ifdef pp_GEOMTEST
    if(show_geomtest==1){
      CLIP_GEOMETRY;
      draw_geomtestclip();
      draw_geomtestoutline();
    }
    if(show_cutcells==1)draw_geom_cutcells();
#endif

/* ++++++++++++++++++++++++ draw circular vents +++++++++++++++++++++++++ */

    if(ncvents>0&&visCircularVents!=VENT_HIDE){
      CLIP_GEOMETRY;
      DrawCircVents(visCircularVents);
    }

/* ++++++++++++++++++++++++ draw sensors/sprinklers/heat detectors +++++++++++++++++++++++++ */

    CLIP_GEOMETRY;
    draw_devices();
#ifdef pp_PILOT
    draw_pilot();
#endif    
    SNIFF_ERRORS("after draw_devices");

    if(visaxislabels==1){
      UNCLIP;
      outputAxisLabels();
      SNIFF_ERRORS("after outputAxisLables");
    }


 /* ++++++++++++++++++++++++ draw user ticks +++++++++++++++++++++++++ */

    if(visUSERticks==1){
      antialias(ON);
      UNCLIP;
      draw_user_ticks();
      antialias(OFF);
      SNIFF_ERRORS("after drawticks");
    }

 /* ++++++++++++++++++++++++ draw ticks +++++++++++++++++++++++++ */

    if(visFDSticks==1&&ntickinfo>0){
      UNCLIP;
      drawticks();
      SNIFF_ERRORS("after drawticks");
    }

    /* ++++++++++++++++++++++++ draw ticks +++++++++++++++++++++++++ */

    if(showgravity==1){
      UNCLIP;
      drawaxis();
      SNIFF_ERRORS("after drawaxis");
    }

    /* draw the box framing the simulation (corners at (0,0,0) (xbar,ybar,zbar) */


/* ++++++++++++++++++++++++ draw simulation frame (corners at (0,0,0) and (xbar,ybar,zbar) +++++++++++++++++++++++++ */

    if(isZoneFireModel==0&&visFrame==1&&highlight_flag==2){
      CLIP_GEOMETRY;
      drawoutlines();
      SNIFF_ERRORS("after drawoutlines");
    }

    if(show_rotation_center==1){
      unsigned char pcolor[4];

      CLIP_GEOMETRY;
      glPushMatrix();
      glTranslatef(camera_current->xcen,camera_current->ycen,camera_current->zcen);
      pcolor[0]=255*foregroundcolor[0];
      pcolor[1]=255*foregroundcolor[1];
      pcolor[2]=255*foregroundcolor[2];
      drawsphere(0.03,pcolor);
      glPopMatrix();
    }


/* ++++++++++++++++++++++++ draw mesh +++++++++++++++++++++++++ */

    if(setPDIM==1){
      if(visGrid!=noGridnoProbe){
        int igrid;
        mesh *meshi;

        UNCLIP;
        for(igrid=0;igrid<nmeshes;igrid++){
          meshi=meshinfo+igrid;
          drawgrid(meshi);
          SNIFF_ERRORS("drawgrid");
        }
      }
    }
  } /* end of if(mode==DRAWSCENE) code segment */


/* ++++++++++++++++++++++++ draw selected devices +++++++++++++++++++++++++ */

  if(mode==SELECTOBJECT){
    if(select_device==1){
      CLIP_GEOMETRY;
      draw_devices();
      SNIFF_ERRORS("after drawselect_devices");
      return;
    }
  }

/* ++++++++++++++++++++++++ draw selected avatars +++++++++++++++++++++++++ */

  if(mode==SELECTOBJECT){
    if(select_avatar==1){
      CLIP_GEOMETRY;
      drawselect_avatars();
      SNIFF_ERRORS("after drawselect_avatars");
      return;
    }
  }

/* ++++++++++++++++++++++++ draw selected tours +++++++++++++++++++++++++ */

  if(mode==SELECTOBJECT){
    if(edittour==1&&ntours>0){
      CLIP_GEOMETRY;
      drawselect_tours();
      SNIFF_ERRORS("after drawselect_tours");
      return;
    }
  }


/* ++++++++++++++++++++++++ draw tours +++++++++++++++++++++++++ */

  if(showtours==1){
    CLIP_GEOMETRY;
    drawtours();
    SNIFF_ERRORS("after drawtours");
  }

  /* ++++++++++++++++++++++++ draw stereo parallax indicator +++++++++++++++++++++++++ */
  
  if(show_parallax==1){
    UNCLIP;
    antialias(ON);
    glLineWidth(linewidth);
    glBegin(GL_LINES);
    glColor3fv(foregroundcolor);
    glVertex3f(0.75,0.0,0.25);
    glVertex3f(0.75,1.0,0.25);
    glEnd();
    antialias(OFF);
  }

  /* ++++++++++++++++++++++++ draw blockages +++++++++++++++++++++++++ */

  CLIP_GEOMETRY;
  drawBlockages(mode,DRAW_OPAQUE);
  SNIFF_ERRORS("drawBlockages");

  /* ++++++++++++++++++++++++ draw triangles +++++++++++++++++++++++++ */
  
  if(ngeominfoptrs>0){
    CLIP_GEOMETRY;
    draw_geom(DRAW_OPAQUE,GEOM_STATIC);
    draw_geom(DRAW_OPAQUE,GEOM_DYNAMIC);
  }

/* ++++++++++++++++++++++++ draw shooter points +++++++++++++++++++++++++ */

  if(showshooter!=0&&shooter_active==1){
    CLIP_VALS;
    draw_shooter();
  }

/* ++++++++++++++++++++++++ draw terrain +++++++++++++++++++++++++ */

  if(visTerrainType!=TERRAIN_HIDDEN&&nterraininfo>0){
    int i;
    
    //shaded 17 0
    //stepped 18 1
    //line    19 2
    //texture 20 3
    //hidden 20 4

    CLIP_GEOMETRY;
    for(i=0;i<nterraininfo;i++){
      terraindata *terri;
      int only_geom;

      terri = terraininfo + i;
      if(terri->loaded==1){
        only_geom=0;
      }
      else{
        only_geom=1;
      }
      switch(visTerrainType){
        case TERRAIN_3D:
          drawterrain(terri,only_geom);
          break;
        case TERRAIN_2D_STEPPED:
          if(cullfaces==1)glDisable(GL_CULL_FACE);
          glPushMatrix();
          glScalef(SCALE2SMV(1.0),SCALE2SMV(1.0),SCALE2SMV(1.0));
          glTranslatef(-xbar0,-ybar0,-zbar0);
          DrawContours(&meshinfo[i].terrain_contour);
          glPopMatrix();
          if(cullfaces==1)glEnable(GL_CULL_FACE);
          break;
        case TERRAIN_2D_LINE:
          glPushMatrix();
          glScalef(SCALE2SMV(1.0),SCALE2SMV(1.0),SCALE2SMV(1.0));
          glTranslatef(-xbar0,-ybar0,-zbar0);
          DrawLineContours(&meshinfo[i].terrain_contour,1.0);
          glPopMatrix();
          break;
        case TERRAIN_3D_MAP:
          if(terrain_texture!=NULL&&terrain_texture->loaded==1){
            drawterrain_texture(terri,only_geom);
          }
          else{
            drawterrain(terri,only_geom);
          }
          break;
        default:
          ASSERT(FFALSE);
          break;
      }
    }
  }

/* ++++++++++++++++++++++++ draw slice files +++++++++++++++++++++++++ */

  if(show_gslice_triangles==1||show_gslice_normal==1||show_gslice_normal_keyboard==1||show_gslice_triangulation==1){
    CLIP_VALS;
    drawgslice_outline();
  }
  if((show_slices_and_vectors==1&&showvslice==1)||(showslice==1&&use_transparency_data==0)){
    CLIP_VALS;
    drawslice_frame();
  } 

  /* ++++++++++++++++++++++++ draw boundary files +++++++++++++++++++++++++ */

  if(showpatch==1){
    CLIP_VALS;
    drawpatch_frame();
  }

/* ++++++++++++++++++++++++ draw labels +++++++++++++++++++++++++ */

  if(visLabels==1){
    CLIP_GEOMETRY;
    drawLabels();
  }

/* ++++++++++++++++++++++++ draw animated isosurfaces +++++++++++++++++++++++++ */

    //if(isoinfo!=NULL)drawspherepoints(sphereinfo);
  if(showiso==1){
    CLIP_VALS;
    drawiso(DRAW_OPAQUE);
  }

/* ++++++++++++++++++++++++ draw zone fire modeling info +++++++++++++++++++++++++ */

  if(nrooms>0){
    CLIP_GEOMETRY;
    drawroomgeom();
    SNIFF_ERRORS("after drawroomgeom");
  }
  if(nrooms>0){
    if(showzone==1){
      CLIP_VALS;
      drawfiredata();
      SNIFF_ERRORS("after drawroomdata");
      if(ReadZoneFile==1&&nzvents>0){
        drawventdata();
        SNIFF_ERRORS("after drawventdata");
      }
    }
  }


//**********************************************************************************
//**********************************************************************************
//**********************************************************************************
//    nothing transparent should be drawn before this portion of the code
//    (ie draw all opaque objects first then draw transparent objects
//**********************************************************************************
//**********************************************************************************
//**********************************************************************************

  /* ++++++++++++++++++++++++ draw triangles +++++++++++++++++++++++++ */
  
  if(ngeominfoptrs>0){
    CLIP_GEOMETRY;
    draw_geom(DRAW_TRANSPARENT,GEOM_STATIC);
    draw_geom(DRAW_TRANSPARENT,GEOM_DYNAMIC);
  }

  if(showiso==1){
    CLIP_VALS;
    drawiso(DRAW_TRANSPARENT);
  }

/* ++++++++++++++++++++++++ draw transparent faces +++++++++++++++++++++++++ */

  CLIP_GEOMETRY;
  draw_transparent_faces();

/* ++++++++++++++++++++++++ draw 3D smoke +++++++++++++++++++++++++ */

  if(show3dsmoke==1||showvolrender==1){
    CLIP_VALS;
    drawsmoke_frame();
  }

  if(active_smokesensors==1&&show_smokesensors!=0){
    CLIP_VALS;
    getsmokesensors();
    draw_devices_val();
  }

/* ++++++++++++++++++++++++ draw zone fire modeling info +++++++++++++++++++++++++ */

  if(nrooms>0&&showzone==1){
    CLIP_VALS;
    drawroomdata();
    SNIFF_ERRORS("after drawroomdata");
  }

/* ++++++++++++++++++++++++ draw slice files +++++++++++++++++++++++++ */

  if((show_slices_and_vectors==1&&showvslice==1)||(showslice==1&&use_transparency_data==1)){
    CLIP_VALS;
    drawslice_frame();
    SNIFF_ERRORS("after drawslice_frame");
  } 

/* ++++++++++++++++++++++++ draw transparent blockages +++++++++++++++++++++++++ */

//  draw_demo(20,20);
//  draw_demo2(1);
  CLIP_GEOMETRY;
  drawBlockages(mode,DRAW_TRANSPARENT);
  SNIFF_ERRORS("after drawBlokcages");

/* ++++++++++++++++++++++++ draw vector slice files +++++++++++++++++++++++++ */

  if(showvslice==1){
    CLIP_VALS;
    drawvslice_frame();
  }
  SNIFF_ERRORS("after drawvslice");

/* ++++++++++++++++++++++++ draw plot3d files +++++++++++++++++++++++++ */

  if(showplot3d==1){
    CLIP_VALS;
    drawplot3d_frame();
  }
  SNIFF_ERRORS("after drawplot3d");
}
BOOL DTM2D::DrawContours(CONTOUR_MAP *ctr)
{

	/**************************************************************************
	*
	*  function name: draw_contours
	*
	*     Generates a contour map from a gridded DTM.  Does not produce vector
	*     information, only a plot on screen.
	*
	*     Reference:
	*
	*        Chris Johnston 1986
	*        Contour plots of large data sets.
	*        Computer Language.
	*        May 1986.
	*
	*
	*     cell vertex and side numbering
	*
	*        2----------1----------3
	*        | \                 / |
	*        |   \             /   |
	*        |     5         6     |
	*        |       \     /       |
	*        0         \ /         2
	*        |         / \         |
	*        |       /     \       |
	*        |     4         7     |
	*        |   /             \   |
	*        | /                 \ |
	*        1----------3----------0
	*  description:
	*
	*     Given a dtm file name, contour interval information, colors, and
	*     the desired area within the DTM, draw contours() draws the contour
	*     lines for the dtm unit.  Assumes that all screen scaling and
	*     windowing has already been done.
	*
	*  return value:
	*
	*     Returns 0 to indicate success, -1 to indicate error.
	*
	**************************************************************************/

	long i;                          // loop counter 
	long j;                          // loop counter 
	int l;                           // loop counter for contour levels 
	int start_level;                 // starting contour level for a column 
	int end_level;                   // ending contour level for a column 
	int k;                           // loop counter for cell side crossings 
	int flag;                        // flag to control pen status (up or down) 
	int cell_index;                  // index into edge crossing array 
	int exit_key = 0;				 // keystroke...only [Esc] terminates 
	long start_col;                  // starting column to be contoured 
	long stop_col;                   // ending column to be contoured 
	long start_point;                // starting point to be contoured 
	long stop_point;                 // ending point to be contoured 
	long test_point;				 // temporary value for testing end of grid 
	long leftover_col;               // extra columns not contoured on first pass 
	long leftover_point;             // extra points not contoured on first pass 
	float ave_elev;                  // average elevation of a cell 
	float x_mult = 1.0f;             // relative distance along a cell edge in X 
	float y_mult = 1.0f;             // relative distance along a cell edge in Y 
	double column_x;                 // X coordinate of column (left side) 
	double x, y;					 // point on line
	void *e1 = NULL;                // pointer to array of elevation data 
	void *e2 = NULL;                // pointer to array of elevation data 
	void *temp = NULL;              // temporary...used when swapping e1 and e2 
	POINT pt;						 // screen point
	CONTOUR_MAP temp_ctr;			 // CONTOUR_MAP structure used for recursive calls 
	MSG stopmsg;
	WCS wcs;

	if (!Valid)
		return(FALSE);

	// set up scaling using WCS
	wcs.Scale(ctr->pDC, ctr->world_ll.x, ctr->world_ll.y, ctr->world_ur.x, ctr->world_ur.y);
	wcs.IsoAdjust(ctr->pDC);

	// calculate the starting row and column 
	start_col = (long) floor((ctr->lower_left.x - Header.origin_x) / Header.column_spacing);
	stop_col = (long) ceil((ctr->upper_right.x - Header.origin_x) / Header.column_spacing);
	start_point = (long) floor((ctr->lower_left.y - Header.origin_y) / Header.point_spacing);
	stop_point = (long) ceil((ctr->upper_right.y - Header.origin_y) / Header.point_spacing);

	if (start_col < 0)
		start_col = 0;
	if (stop_col > (Header.columns - 1))
		stop_col = Header.columns - 1;
	if (start_point < 0)
		start_point = 0;
	if (stop_point > (Header.points - 1))
		stop_point = Header.points - 1;

	// if we have elevations in memory, work from memory
	if (HaveElevations) {
		e2 = lpsElevData[start_col];
	}
	else {
		int sizes[] = {sizeof(short), sizeof(int), sizeof(float), sizeof(double)};

		// otherwise read from file
		// open the dtm file 
		if (!OpenModelFile())
			return(FALSE);

		// allocate memory for 2 profiles of dtm data 
		e1 = (void *) malloc((size_t) Header.points * sizes[Header.z_bytes]);

		// check for allocation problems 
		if (!e1) {
			CloseModelFile();

			return(FALSE);
		}

		e2 = (void *) malloc((size_t) Header.points * sizes[Header.z_bytes]);

		// check for allocation problems 
		if (!e2) {
			free(e1);
			CloseModelFile();

			return(FALSE);
		}

		// read the first profile into e2...will be swapped to e1 in loop 
		if (LoadDTMProfile(start_col, e2)) {
			free(e1);
			free(e2);
			CloseModelFile();

			return(FALSE);
		}
	}

	// sweep through the cells and draw contours 
	for (i = start_col; i < stop_col; i += ctr->column_smooth) {
		// check for last column 
		if (i + ctr->column_smooth > stop_col)
			break;

		// calculate the x for the column 
		column_x = Header.origin_x + ((double) i * Header.column_spacing);

		// swap pointers to elevation arrays 
		temp = e1;
		e1 = e2;
		e2 = temp;

		// read next profile 
		if (HaveElevations) 
			e2 = lpsElevData[i + ctr->column_smooth];
		else {
			if (LoadDTMProfile(i + ctr->column_smooth, e2)) {
				free(e1);
				free(e2);
				CloseModelFile();

				return(FALSE);
			}
		}

		// set color for normal interval 
		ctr->pDC->SelectObject(ctr->cpNormalPen);

		// calculate test point for end of data 
		test_point = stop_point - ctr->point_smooth;

		for (j = start_point; j < stop_point; j += ctr->point_smooth) {
			// check for last point 
			if (j > test_point)
				break;

			if (!ctr->DrawZeroLine) {
				// check for 1 or more void area markers (-1) and skip cell 
				if (ReadColumnValue(e1, j) < 0 || ReadColumnValue(e2, j) < 0 || ReadColumnValue(e1, j+ ctr->point_smooth) < 0 || ReadColumnValue(e2, j + ctr->point_smooth) < 0)
					continue;
			}

			// determine cell min/max elevations 
			start_level = (int) __min(ReadColumnValue(e1, j), ReadColumnValue(e2, j));
			start_level = (int) __min(start_level, ReadColumnValue(e1, j + ctr->point_smooth));
			start_level = (int) __min(start_level, ReadColumnValue(e2, j + ctr->point_smooth));
			start_level = start_level - (start_level % ctr->normal);

			end_level = (int) __max(ReadColumnValue(e1, j), ReadColumnValue(e2, j));
			end_level = (int) __max(end_level, ReadColumnValue(e1, j + ctr->point_smooth));
			end_level = (int) __max(end_level, ReadColumnValue(e2, j + ctr->point_smooth));

			// check cell for each possible contour level 
			// loop using start_level can start at -1...use loop starting at 0
			// to draw 0.0 contour
			for (l = ctr->DrawZeroLine ? 0 : start_level; l <= end_level; l += ctr->normal) {
				// calculate the cell index 
				cell_index = 0;
				if (ReadColumnValue(e2, j) >= l)
					cell_index = 1;
				if (ReadColumnValue(e1, j) >= l)
					cell_index |= 2;
				if (ReadColumnValue(e1, j + ctr->point_smooth) >= l)
					cell_index |= 4;
				if (ReadColumnValue(e2, j + ctr->point_smooth) >= l)
					cell_index |= 8;

				// if cell_index is 0 or 15, no contours at this level 
				if (cell_index == 0 || cell_index == 15)
					continue;

				// calculate the average elevation for the cell,
				// use it to adjust the cell_index 
				ave_elev = ((float) ReadColumnValue(e2, j) + (float) ReadColumnValue(e1, j) + (float) ReadColumnValue(e1, j + ctr->point_smooth) + (float) ReadColumnValue(e2, j + ctr->point_smooth)) / 4.0f;

				if (ave_elev <= (float) l)
					cell_index = cell_index ^ 15;

				// if working on a bold interval, set color to bold color 
				if ((l % ctr->bold) == 0)
					ctr->pDC->SelectObject(ctr->cpBoldPen);

				// set flag to force move to first crossing point 
				flag = 1;

				// step through the side or segment crossings held in the
				// crossing side list 
				for (k = 0; k < em[cell_index] [0]; k ++) {

					// calculate the cell size multiplier...different logic
					// for each side or segment.  Multiplier ranges from 0 to 1 
					switch (el[em[cell_index] [1] + k]) {
						case 0:
							x_mult = 0.0f;
							if (ReadColumnValue(e1, j) == ReadColumnValue(e1, j + ctr->point_smooth))
								y_mult = 0.5f;
							else
								y_mult = ((float) (l - ReadColumnValue(e1, j))) / ((float) (ReadColumnValue(e1, j + ctr->point_smooth) - ReadColumnValue(e1, j)));
							break;
						case 1:
							if (ReadColumnValue(e1, j + ctr->point_smooth) == ReadColumnValue(e2, j + ctr->point_smooth))
								x_mult = 0.5f;
							else
								x_mult = ((float) (l - ReadColumnValue(e1, j + ctr->point_smooth))) / ((float) (ReadColumnValue(e2, j + ctr->point_smooth) - ReadColumnValue(e1, j + ctr->point_smooth)));
							y_mult = 1.0f;
							break;
						case 2:
							x_mult = 1.0f;
							if (ReadColumnValue(e2, j) == ReadColumnValue(e2, j + ctr->point_smooth))
								y_mult = 0.5f;
							else
								y_mult = 1.0f - (((float) (l - ReadColumnValue(e2, j + ctr->point_smooth))) / ((float) (ReadColumnValue(e2, j) - ReadColumnValue(e2, j + ctr->point_smooth))));
							break;
						case 3:
							if (ReadColumnValue(e1, j) == ReadColumnValue(e2, j))
								x_mult = 0.5f;
							else
								x_mult = 1.0f - (((float) (l - ReadColumnValue(e2, j))) / ((float) (ReadColumnValue(e1, j) - ReadColumnValue(e2, j))));
							y_mult = 0.0f;
							break;
						case 4:
							if (ave_elev == (float) ReadColumnValue(e1, j))
								x_mult = 0.25f;
							else
								x_mult = 0.5f * ((float) (l - ReadColumnValue(e1, j))) / (ave_elev - (float) ReadColumnValue(e1, j));
							y_mult = x_mult;
							break;
						case 5:
							if (ave_elev == (float) ReadColumnValue(e1, j + ctr->point_smooth))
								x_mult = 0.25f;
							else
								x_mult = 0.5f * ((float) (l - ReadColumnValue(e1, j + ctr->point_smooth))) / (ave_elev - (float) ReadColumnValue(e1, j + ctr->point_smooth));
							y_mult = 1.0f - x_mult;
							break;
						case 6:
							if (ave_elev == (float) ReadColumnValue(e2, j + ctr->point_smooth))
								x_mult =  0.75f;
							else
								x_mult = 1.0f - (0.5f * ((float) (l - ReadColumnValue(e2, j + ctr->point_smooth))) / (ave_elev - (float) ReadColumnValue(e2, j + ctr->point_smooth)));
							y_mult = x_mult;
							break;
						case 7:
							if (ave_elev == (float) ReadColumnValue(e2, j))
								x_mult = 0.75f;
							else
								x_mult = 1.0f - (0.5f * ((float) (l - ReadColumnValue(e2, j))) / (ave_elev - (float) ReadColumnValue(e2, j)));
							y_mult = 1.0f - x_mult;
							break;
						case 8:
							flag = 1;
							continue;
					}
					// move or draw to the crossing point depending on flag 
					x = column_x + Header.column_spacing * (double) x_mult * (double) ctr->column_smooth;
					y = Header.origin_y + ((double) j * Header.point_spacing) + Header.point_spacing * (double) y_mult * (double) ctr->point_smooth;

					// scale to window coords
					pt.x = wcs.WX(x);
					pt.y = wcs.WY(y);

					if (flag) {
						ctr->pDC->MoveTo(pt);
						flag = 0;
					}
					else {
						ctr->pDC->LineTo(pt);
						if ((l % ctr->bold) == 0)
							ctr->pDC->SetPixel(pt, ctr->bcolor);
						else
							ctr->pDC->SetPixel(pt, ctr->ncolor);
					}
				}
				// if working on a bold interval, reset color to normal 
				if ((l % ctr->bold) == 0)
					ctr->pDC->SelectObject(ctr->cpNormalPen);

				// if working on 0 contour, jump to actual start level 
				if (l == 0) {
					l = start_level - ctr->normal;
					// check for void area markers...(-1) 
					if (ReadColumnValue(e1, j) < 0 || ReadColumnValue(e2, j) < 0 || ReadColumnValue(e1, j + ctr->point_smooth) < 0 || ReadColumnValue(e2, j + ctr->point_smooth) < 0)
						break;
				}
			}
		}
		// check for an [Esc] key press
		if (!ctr->pDC->IsPrinting()) {
			if (PeekMessage(&stopmsg, ctr->pDC->GetWindow()->m_hWnd, WM_KEYUP, WM_KEYUP, PM_REMOVE)) {
				if (stopmsg.wParam == VK_ESCAPE) {
					exit_key = 27;
					break;
				}
			}
		}
	}
	if (!HaveElevations) {
		// free profile arrays and close dtm file 
		free(e1);
		free(e2);
		fclose(modelfile);
	}

	if (exit_key == 27)
		return(TRUE);

	// check to see if there is an uncontoured strip along right side 
	leftover_col = (stop_col - start_col) % ctr->column_smooth;
	leftover_point = (stop_point - start_point) % ctr->point_smooth;

	temp_ctr = *ctr;
	temp_ctr.column_smooth = (short) leftover_col;
	temp_ctr.lower_left.x = Header.origin_x + (stop_col - leftover_col) * Header.column_spacing + (Header.column_spacing * 0.1);

	if (leftover_col) {
		DrawContours(&temp_ctr);
	}

	temp_ctr.column_smooth = ctr->column_smooth;
	temp_ctr.lower_left.x = ctr->lower_left.x;
	temp_ctr.lower_left.y = Header.origin_y + (stop_point - leftover_point) * Header.point_spacing + (Header.point_spacing * 0.1);
	temp_ctr.point_smooth = (short) leftover_point;

	// check to see if there is an uncontoured strip along the top 
	if (leftover_point) {
		DrawContours(&temp_ctr);
	}

	// draw neat line
	if (ctr->DrawNeatLine) {
		ctr->pDC->SelectObject(ctr->cpNormalPen);
		ctr->pDC->SelectStockObject(NULL_BRUSH);
		ctr->pDC->Rectangle(wcs.WX(OriginX()), wcs.WY(OriginY()), wcs.WX(OriginX() + Width()), wcs.WY(OriginY() + Height()));
	}

	return(TRUE);
}