////////////////////////////////////////////////////////// // TMapDC // ------ // draw a Vertex void TMapDC::DrawMapVertex (int editmode, SHORT vnum) { assert_vnum (vnum); if ( editmode != OBJ_VERTEXES ) return; Vertex ve = Vertexes[vnum]; SHORT x0 = ve.x - OBJSIZE; SHORT y0 = ve.y - OBJSIZE; SHORT x1 = ve.x + OBJSIZE; SHORT y1 = ve.y + OBJSIZE; #ifndef WINDOWS_CLIPPING if ( ! IS_VISIBLE_MAP_RECT(x0, y0, x1, y1) ) return; #endif // Draw a point if cross is small SetPenColor16 (LIGHTGREEN); // if ( ((x1 - x0) * MUL_SCALE) <= 3 ) // Draw point if Scale <= 1/6 if ( (ScaleNum == 1) && (ScaleDen >= 6) ) { #ifdef WINDOWS_SCALING SHORT x = ve.x; SHORT y = ve.y; #else SHORT x = SCREENX(ve.x); SHORT y = SCREENY(ve.y); #endif MoveTo (x, y); LineTo (x + 1, y); // SetPixel (SCREENX(ve.x), SCREENY(ve.y), GetColor16(LIGHTGREEN)); // SetPixel (ve.x, ve.y, GetColor16(LIGHTGREEN)); // ::SetPixel (*this, SCREENX(ve.x), SCREENY(ve.y), Color16Tab[LIGHTGREEN]); } else { #ifndef WINDOWS_SCALING x0 = SCREENX(x0); y0 = SCREENY(y0); x1 = SCREENX(x1); y1 = SCREENY(y1); #endif MoveTo(x0, y0); LineTo(x1, y1); MoveTo(x1, y0); LineTo(x0, y1); } }
////////////////////////////////////////////////////////// // TMapDC // ------ // draw a circle on the screen from map coords void TMapDC::DrawMapCircle(SHORT mapXcenter, SHORT mapYcenter, SHORT mapRadius) { SHORT radius; SHORT x0 = mapXcenter - mapRadius; SHORT y0 = mapYcenter + mapRadius; SHORT x1 = mapXcenter + mapRadius; SHORT y1 = mapYcenter - mapRadius; #ifndef WINDOWS_CLIPPING if ( ! IS_VISIBLE_MAP_RECT(x0,y0,x1,y1) ) return; #endif radius = mapRadius * ScaleNum / ScaleDen; #ifndef WINDOWS_SCALING x0 = SCREENX(x0); y0 = SCREENY(y0); x1 = SCREENX(x1); y1 = SCREENY(y1); #endif // LogMessage ("DrawMapCircle(%d,%d,%d,%d)\n", x0, y0, x1, y1); // SelectStockObject (NULL_BRUSH); // If radius is small, draw a rectangle instead of an ellipse if ( radius <= 3 ) { TPoint points[5], *pp = points ; #ifdef WINDOWS_SCALING pp->x = mapXcenter; pp->y = y0; pp++; pp->x = x1; pp->y = mapYcenter; pp++; pp->x = mapXcenter; pp->y = y1; pp++; pp->x = x0; pp->y = mapYcenter; pp++; pp->x = mapXcenter; pp->y = y0; #else pp->x = x0+radius; pp->y = y0; pp++; pp->x = x1; pp->y = y0+radius; pp++; pp->x = x0+radius; pp->y = y1; pp++; pp->x = x0; pp->y = y0+radius; pp++; pp->x = x0+radius; pp->y = y0; #endif Polyline (points, 5); } else { Ellipse (x0, y0, x1+1, y1+1); } }
////////////////////////////////////////////////////////// // TMapDC // ------ // draw a rectangle on the screen from map coords void TMapDC::DrawMapRect(SHORT mapXstart, SHORT mapYstart, SHORT mapXend, SHORT mapYend) { // LogMessage ("DrawMapRect(%d,%d,%d,%d)\n", mapXstart, mapYstart, mapXend, mapYend); #ifndef WINDOWS_CLIPPING if ( ! IS_VISIBLE_MAP_RECT(mapXstart, mapYstart, mapXend, mapYend) ) return; #endif #ifdef WINDOWS_SCALING Rectangle (mapXstart, mapYstart, mapXend, mapYend); #else Rectangle (SCREENX(mapXstart), SCREENY(mapYstart), SCREENX(mapXend), SCREENY(mapYend)); #endif }
////////////////////////////////////////////////////////// // TMapDC // ------ // draw a vector (line with an ending arrow) on the screen // from map coords void TMapDC::DrawMapVector(SHORT mapXstart, SHORT mapYstart, SHORT mapXend, SHORT mapYend) { #ifndef WINDOWS_CLIPPING if ( ! IS_VISIBLE_MAP_RECT(mapXstart, mapYstart, mapXend, mapYend) ) return; #endif #ifdef WINDOWS_SCALING SHORT x0 = mapXstart; SHORT y0 = mapYstart; SHORT x1 = mapXend; SHORT y1 = mapYend; #else SHORT x0 = SCREENX(mapXstart); SHORT y0 = SCREENY(mapYstart); SHORT x1 = SCREENX(mapXend); SHORT y1 = SCREENY(mapYend); #endif SHORT dx = x0 - x1; SHORT dy = y0 - y1; // Draw the line part of the vector MoveTo (x0, y0); LineTo (x1, y1); // Don't draw arrow if Scale <= 1/6 if ( (ScaleNum == 1) && (ScaleDen >= 6) ) return; // Calc the length of the line SHORT r = (SHORT)hypot(dx, dy); // Don't calc if length == 0 (no orientation !) if ( r == 0 ) return; // Draw the arrow part of the vector SHORT scrXoff = (SHORT) (dx * 8 * MUL_SCALE / r); SHORT scrYoff = (SHORT) (dy * 8 * MUL_SCALE / r); x0 = x1 + 2 * scrXoff; y0 = y1 + 2 * scrYoff; MoveTo (x0 - scrYoff, y0 + scrXoff); LineTo (x1 , y1); LineTo (x0 + scrYoff, y0 - scrXoff); }
/* * This routine draws the title of the graph centered in * the window. It is spaced down from the top by an amount * specified by the constant PADDING. The font must be * fixed width. The routine returns the height of the * title in pixels. */ void DrawLabel(char *gw, GraphWin * wi) { LabelList *spot; int code1; for(spot = wi->Label; spot; spot = spot->next) { C_CODE(spot->x, spot->y, code1); if (!code1) wi->dev_info.xg_text(gw, SCREENX(wi, spot->x), SCREENY(wi, spot->y), spot->label, spot->just, spot->style); } }
////////////////////////////////////////////////////////// // TMapDC // ------ // draw a LineDef void TMapDC::DrawLineDefLen (SHORT x0, SHORT y0, SHORT x1, SHORT y1, int color) { char Text[10]; // How to display a Text using a XOR mode? // 1. Create a memory dc // 2. Calc the text size (GetTextExtent) // 3. Create a bitmap of this size // 4. Draw text in bitmap (TextOut) in the memory DC // 5. Draw bitmap (with text in it) on screen using XOR // Build the string of the line length sprintf (Text, "%d", ComputeDist (abs(x1 - x0), abs(y1 - y0))); // Get the text size TSize TextSize = GetTextExtent(Text, strlen(Text)); // Calc. the text drawing rect #ifdef WINDOWS_SCALING TRect TTextRect(TPoint ((x0 + x1) / 2, (y0 + y1) /2), TextSize)); #else TRect TTextRect(TPoint (SCREENX((x0 + x1) / 2), SCREENY((y0 + y1) /2)), TextSize); #endif // Draw text in bitmap TMemoryDC MemDC; TBitmap TextBitmap (*this, TextSize.cx, TextSize.cy); MemDC.SelectObject (TextBitmap); MemDC.SetTextAlign (TA_LEFT); MemDC.SetBkMode (TRANSPARENT); MemDC.SetTextColor (GetColor16(BLUE)); MemDC.SelectObject (TPen(GetColor16(color))); MemDC.SelectObject (TBrush(GetColor16(WHITE))); MemDC.Rectangle (TPoint(0, 0), TextSize); MemDC.TextOut (0, 0, Text); // Draw bitmap (with text in it) on screen using XOR // TTextRect.left -= TextSize.cx; // align to right BitBlt (TTextRect, MemDC, TPoint(0, 0), SRCINVERT); }
/* * This routine draws grid line labels in engineering notation, * the grid lines themselves, and unit labels on the axes. */ int DrawGridAndAxis(char *w, GraphWin * wi) { int startX; int Yspot, Xspot; double Xincr, Yincr, Xstart, Ystart, Yindex, Xindex; XSegment segs[2]; double initGrid(), stepGrid(); int tickFlag = FALSE; int logXFlag = wi->logx; int logYFlag = wi->logy; char *XUnitText = wi->XUnitText; char *YUnitText = wi->YUnitText; XSegment bb[4]; /* * With the powers computed, we can draw the axis labels. */ Yspot = wi->dev_info.bdr_pad * 2 + wi->dev_info.title_height; wi->dev_info.xg_text(w, wi->dev_info.bdr_pad, Yspot, YUnitText, T_UPPERLEFT, T_AXIS); startX = wi->dev_info.area_w - wi->dev_info.bdr_pad; wi->dev_info.xg_text(w, startX, wi->XOppY, XUnitText, T_RIGHT, T_AXIS); /* * First, the grid line labels */ Yincr = (wi->dev_info.axis_pad + wi->dev_info.axis_height) * wi->YUnitsPerPixel; Ystart = initGrid(wi->UsrOrgY, Yincr, logYFlag); for (Yindex = Ystart; Yindex < wi->UsrOppY; Yindex = stepGrid()) { Yspot = SCREENY(wi, Yindex); /* Write the axis label */ if ( !logYFlag && ( fabs(Yindex/Yincr) < 1.0e-3 ) ) DrawNumber(w, wi, 0.0, wi->dev_info.bdr_pad + (8 * wi->dev_info.axis_width), Yspot, T_RIGHT, logYFlag); else if (wi->xg_yscl < 0.0) DrawNumber(w, wi, -Yindex, wi->dev_info.bdr_pad + (8 * wi->dev_info.axis_width), Yspot, T_RIGHT, logYFlag); else DrawNumber(w, wi, Yindex, wi->dev_info.bdr_pad + (8 * wi->dev_info.axis_width), Yspot, T_RIGHT, logYFlag); } Xincr = (wi->dev_info.axis_pad + (wi->dev_info.axis_width * 7)) * wi->XUnitsPerPixel; Xstart = initGrid(wi->UsrOrgX, Xincr, logXFlag); for (Xindex = Xstart; Xindex < wi->UsrOppX; Xindex = stepGrid()) { Xspot = SCREENX(wi, Xindex); /* Write the axis label */ if ( !logXFlag && ( fabs(Xindex/Xincr) < ZERO_THRES ) ) DrawNumber(w, wi, 0.0, Xspot, wi->dev_info.area_h - wi->dev_info.bdr_pad, T_BOTTOM, logXFlag); else if (wi->xg_xscl < 0.0) DrawNumber(w, wi, -Xindex, Xspot, wi->dev_info.area_h - wi->dev_info.bdr_pad, T_BOTTOM, logXFlag); else DrawNumber(w, wi, Xindex, Xspot, wi->dev_info.area_h - wi->dev_info.bdr_pad, T_BOTTOM, logXFlag); } /* * Now, the grid lines or tick marks */ Yincr = (wi->dev_info.axis_pad + wi->dev_info.axis_height) * wi->YUnitsPerPixel; Ystart = initGrid(wi->UsrOrgY, Yincr, logYFlag); for (Yindex = Ystart; Yindex < wi->UsrOppY; Yindex = stepGrid()) { Yspot = SCREENY(wi, Yindex); /* Draw the grid line or tick mark */ if (tickFlag) { segs[0].x1 = wi->XOrgX; segs[0].x2 = wi->XOrgX + wi->dev_info.tick_len; segs[1].x1 = wi->XOppX - wi->dev_info.tick_len; segs[1].x2 = wi->XOppX; segs[0].y1 = segs[0].y2 = segs[1].y1 = segs[1].y2 = Yspot; } else { segs[0].x1 = wi->XOrgX; segs[0].x2 = wi->XOppX; segs[0].y1 = segs[0].y2 = Yspot; } if ((fabs(Yindex) < ZERO_THRES) && !logYFlag) { wi->dev_info.xg_seg(w, 1, segs, 0, L_ZERO, 0, 0); if (tickFlag) { wi->dev_info.xg_seg(w, 1, &(segs[1]), 0, L_ZERO, 0, 0); } } else { wi->dev_info.xg_seg(w, 1, segs, 0, L_AXIS, 0, 0); if (tickFlag) { wi->dev_info.xg_seg(w, 1, &(segs[1]), 0, L_AXIS, 0, 0); } } } Xincr = (wi->dev_info.axis_pad + (wi->dev_info.axis_width * 7)) * wi->XUnitsPerPixel; Xstart = initGrid(wi->UsrOrgX, Xincr, logXFlag); for (Xindex = Xstart; Xindex < wi->UsrOppX; Xindex = stepGrid()) { Xspot = SCREENX(wi, Xindex); /* Draw the grid line or tick marks */ if (tickFlag) { segs[0].x1 = segs[0].x2 = segs[1].x1 = segs[1].x2 = Xspot; segs[0].y1 = wi->XOrgY; segs[0].y2 = wi->XOrgY + wi->dev_info.tick_len; segs[1].y1 = wi->XOppY - wi->dev_info.tick_len; segs[1].y2 = wi->XOppY; } else { segs[0].x1 = segs[0].x2 = Xspot; segs[0].y1 = wi->XOrgY; segs[0].y2 = wi->XOppY; } if ((fabs(Xindex) < ZERO_THRES) && !logXFlag) { wi->dev_info.xg_seg(w, 1, segs, 0, L_ZERO, 0, 0); if (tickFlag) { wi->dev_info.xg_seg(w, 1, &(segs[1]), 0, L_ZERO, 0, 0); } } else { wi->dev_info.xg_seg(w, 1, segs, 0, L_AXIS, 0, 0); if (tickFlag) { wi->dev_info.xg_seg(w, 1, &(segs[1]), 0, L_AXIS, 0, 0); } } } /* Draw bounding box */ bb[0].x1 = bb[0].x2 = bb[1].x1 = bb[3].x2 = wi->XOrgX; bb[0].y1 = bb[2].y2 = bb[3].y1 = bb[3].y2 = wi->XOrgY; bb[1].x2 = bb[2].x1 = bb[2].x2 = bb[3].x1 = wi->XOppX; bb[0].y2 = bb[1].y1 = bb[1].y2 = bb[2].y1 = wi->XOppY; wi->dev_info.xg_seg(w, 4, bb, 0, L_AXIS, 0, 0); }
/* * This routine draws the data sets themselves using the macros * for translating coordinates. */ int DrawData(char *w, GraphWin *wi) { DataSet *temp; double sx1, sy1, sx2, sy2, tx, ty; int idx, subindex; int code1, code2, cd, mark_inside; int X_idx; XSegment *ptr; PointList *thisList; int markFlag; int noLines = FALSE; int lineWidth = 0; /*make sure Xsegs is big enough*/ if ((X_idx = rdFindMax(wi)) > wi->max_segs) { wi->max_segs += X_idx + 100; wi->Xsegs = (XSegment *) realloc(wi->Xsegs, (unsigned) (wi->max_segs * sizeof(XSegment))); } for(idx = 0, temp = wi->Data; temp != NULL; temp = temp->next, idx++) { thisList = temp->list; markFlag = temp->marker; while (thisList) { X_idx = 0; for (subindex = 0; subindex < thisList->numPoints-1; subindex++) { /* Put segment in (sx1,sy1) (sx2,sy2) */ sx1 = thisList->xvec[subindex]; sy1 = thisList->yvec[subindex]; sx2 = thisList->xvec[subindex+1]; sy2 = thisList->yvec[subindex+1]; /* Now clip to current window boundary */ C_CODE(sx1, sy1, code1); C_CODE(sx2, sy2, code2); mark_inside = (code1 == 0); while (code1 || code2) { if (code1 & code2) break; cd = (code1 ? code1 : code2); if (cd & LEFT_CODE) { /* Crosses left edge */ ty = sy1 + (sy2 - sy1) * (wi->UsrOrgX - sx1) / (sx2 - sx1); tx = wi->UsrOrgX; } else if (cd & RIGHT_CODE) { /* Crosses right edge */ ty = sy1 + (sy2 - sy1) * (wi->UsrOppX - sx1) / (sx2 - sx1); tx = wi->UsrOppX; } else if (cd & BOTTOM_CODE) { /* Crosses bottom edge */ tx = sx1 + (sx2 - sx1) * (wi->UsrOrgY - sy1) / (sy2 - sy1); ty = wi->UsrOrgY; } else if (cd & TOP_CODE) { /* Crosses top edge */ tx = sx1 + (sx2 - sx1) * (wi->UsrOppY - sy1) / (sy2 - sy1); ty = wi->UsrOppY; } if (cd == code1) { sx1 = tx; sy1 = ty; C_CODE(sx1, sy1, code1); } else { sx2 = tx; sy2 = ty; C_CODE(sx2, sy2, code2); } } if (!code1 && !code2) { /* Add segment to list */ wi->Xsegs[X_idx].x1 = SCREENX(wi, sx1); wi->Xsegs[X_idx].y1 = SCREENY(wi, sy1); wi->Xsegs[X_idx].x2 = SCREENX(wi, sx2); wi->Xsegs[X_idx].y2 = SCREENY(wi, sy2); X_idx++; } /* Draw markers if requested and they are in drawing region */ if (markFlag && mark_inside) { /* Distinctive markers */ wi->dev_info.xg_dot(w, wi->Xsegs[X_idx-1].x1, wi->Xsegs[X_idx-1].y1, P_MARK, idx, idx); } } /* Handle last marker */ if (markFlag && (thisList->numPoints > 0)) { C_CODE(thisList->xvec[thisList->numPoints-1], thisList->yvec[thisList->numPoints-1], mark_inside); if (mark_inside == 0) { /* Distinctive markers */ wi->dev_info.xg_dot(w, wi->Xsegs[X_idx-1].x2, wi->Xsegs[X_idx-1].y2, P_MARK, idx, idx); } } /* Draw segments */ if (thisList->numPoints > 0 && (!noLines) && (X_idx > 0)) { ptr = wi->Xsegs; while (X_idx > wi->max_segs) { wi->dev_info.xg_seg(w, wi->max_segs, ptr, lineWidth, L_VAR, idx, idx); ptr += wi->max_segs; X_idx -= wi->max_segs; } wi->dev_info.xg_seg(w, X_idx, ptr, lineWidth, L_VAR, idx, idx); } /* Next subset */ thisList = thisList->next; } } }
////////////////////////////////////////////////////////// // TMapDC // ------ // draw a Thing void TMapDC::DrawMapThing (int editmode, SHORT tnum) { assert_tnum (tnum); Thing *pThing = &Things[tnum]; SHORT xpos = pThing->xpos; SHORT ypos = pThing->ypos; SHORT scrRadius; SHORT mapRadius; // Select the radius if (editmode == OBJ_THINGS) mapRadius = GetKodObjectRadius(Things[tnum].type); else mapRadius = OBJSIZE; // Calc. bouding rectangle SHORT x0 = xpos - mapRadius; SHORT y0 = ypos + mapRadius; SHORT x1 = xpos + mapRadius; SHORT y1 = ypos - mapRadius; #ifndef WINDOWS_CLIPPING if ( ! IS_VISIBLE_MAP_RECT(x0,y0,x1,y1) ) return; #endif // Convert map coords. to screen coords. scrRadius = (SHORT)(mapRadius * MUL_SCALE); #ifndef WINDOWS_SCALING xpos = SCREENX(xpos); ypos = SCREENY(ypos); x0 = SCREENX(x0); y0 = SCREENY(y0); x1 = SCREENX(x1); y1 = SCREENY(y1); #endif // Draw bouding circle of the thing if (editmode == OBJ_THINGS) { SetPenColor16 (GetKodObjectColor (Things[tnum].type)); // If radius is small, draw a rectangle instead of an ellipse if ( scrRadius > 4 ) { Ellipse (x0, y0, x1+1, y1+1); } else if ( scrRadius > 1 ) { TPoint points[5], *pp = points ; pp->x = xpos; pp->y = y0; pp++; pp->x = x1; pp->y = ypos; pp++; pp->x = xpos; pp->y = y1; pp++; pp->x = x0; pp->y = ypos; pp++; pp->x = xpos; pp->y = y0; Polyline (points, 5); } } // Set pen color to default (LIGHTGRAY) else SetPenColor16 (LIGHTGRAY); // Draw the cross MoveTo (xpos, y0) ; LineTo (xpos, y1) ; MoveTo (x0, ypos) ; LineTo (x1, ypos) ; }