diff options
author | joye <joye> | 2014-04-07 22:31:06 (GMT) |
---|---|---|
committer | joye <joye> | 2014-04-07 22:31:06 (GMT) |
commit | f9415123449b0a82143ec42be1fba0ab3b3b78fa (patch) | |
tree | 36f27dc9f2ede2a80f300dd6f6804e6befbcfa28 /src | |
parent | ae3cf41403223191dda5efcf6d3a4165649a4a68 (diff) | |
download | blt-f9415123449b0a82143ec42be1fba0ab3b3b78fa.zip blt-f9415123449b0a82143ec42be1fba0ab3b3b78fa.tar.gz blt-f9415123449b0a82143ec42be1fba0ab3b3b78fa.tar.bz2 |
*** empty log message ***
Diffstat (limited to 'src')
-rw-r--r-- | src/bltGrAxis.C | 6 | ||||
-rw-r--r-- | src/bltGrElem.C | 88 | ||||
-rw-r--r-- | src/bltGrElem.h | 87 | ||||
-rw-r--r-- | src/bltGrElemBar.C | 1405 | ||||
-rw-r--r-- | src/bltGrElemBar.h | 86 | ||||
-rw-r--r-- | src/bltGrElemLine.C | 2260 | ||||
-rw-r--r-- | src/bltGrElemLine.h | 125 | ||||
-rw-r--r-- | src/bltGrElemOp.C | 98 | ||||
-rw-r--r-- | src/bltGrPen.C | 13 | ||||
-rw-r--r-- | src/bltGrPenBar.C | 14 | ||||
-rw-r--r-- | src/bltGrPenBar.h | 3 | ||||
-rw-r--r-- | src/bltGrPenLine.C | 12 | ||||
-rw-r--r-- | src/bltGrPenLine.h | 3 | ||||
-rw-r--r-- | src/bltGraph.h | 8 |
14 files changed, 2043 insertions, 2165 deletions
diff --git a/src/bltGrAxis.C b/src/bltGrAxis.C index fa5f0d0..1e8a22c 100644 --- a/src/bltGrAxis.C +++ b/src/bltGrAxis.C @@ -43,6 +43,8 @@ class Marker; #include "bltConfig.h" #include "bltGrElem.h" +#include "bltGrElemBar.h" +#include "bltGrElemLine.h" #include "bltGrAxis.h" #define AXIS_PAD_TITLE 2 @@ -1776,8 +1778,8 @@ void Blt_ResetAxes(Graph* graphPtr) Region2d exts; Element* elemPtr = (Element*)Blt_Chain_GetValue(link); - ElementOptions* ops = (ElementOptions*)elemPtr->ops; - (*elemPtr->procsPtr->extentsProc) (elemPtr, &exts); + ElementOptions* ops = (ElementOptions*)elemPtr->ops(); + elemPtr->extents(&exts); GetDataLimits(ops->axes.x, exts.left, exts.right); GetDataLimits(ops->axes.y, exts.top, exts.bottom); } diff --git a/src/bltGrElem.C b/src/bltGrElem.C index 8a1b972..8156bc9 100644 --- a/src/bltGrElem.C +++ b/src/bltGrElem.C @@ -31,9 +31,73 @@ #include "bltGrElemOp.h" #include "bltGrPenOp.h" -PenStyle** Blt_StyleMap(Element* elemPtr) +Element::Element(Graph* gPtr, const char* name, Tcl_HashEntry* hPtr) { - ElementOptions* ops = (ElementOptions*)elemPtr->ops; + obj.classId = CID_NONE; + obj.name = dupstr(name); + obj.className =NULL; + obj.graphPtr = gPtr; + obj.tags =NULL; + + graphPtr_ = gPtr; + flags =0; + hide_ =0; + hashPtr = hPtr; + ops_ =NULL; + + row_ =0; + col_ =0; + activeIndices_ =NULL; + nActiveIndices_ =0; + optionTable_ =NULL; + xRange_ =0; + yRange_ =0; + link =NULL; +} + +Element::~Element() +{ + if (obj.name) + delete [] obj.name; + if (obj.className) + delete [] obj.className; + + if (activeIndices_) + free(activeIndices_); + + if (hashPtr) + Tcl_DeleteHashEntry(hashPtr); + + Tk_FreeConfigOptions((char*)ops_, optionTable_, obj.graphPtr->tkwin); + + if (ops_) + free(ops_); +} + +double Blt_FindElemValuesMinimum(ElemValues* valuesPtr, double minLimit) +{ + double min = DBL_MAX; + if (!valuesPtr) + return min; + + for (int ii=0; ii<valuesPtr->nValues; ii++) { + double x = valuesPtr->values[ii]; + // What do you do about negative values when using log + // scale values seems like a grey area. Mirror. + if (x < 0.0) + x = -x; + if ((x > minLimit) && (min > x)) + min = x; + } + if (min == DBL_MAX) + min = minLimit; + + return min; +} + +PenStyle** Element::StyleMap() +{ + ElementOptions* ops = (ElementOptions*)ops_; int nPoints = NUMBEROFPOINTS(ops); int nWeights = MIN(ops->w ? ops->w->nValues : 0, nPoints); @@ -82,23 +146,3 @@ void Blt_FreeStylePalette(Blt_Chain stylePalette) } } -double Blt_FindElemValuesMinimum(ElemValues* valuesPtr, double minLimit) -{ - double min = DBL_MAX; - if (!valuesPtr) - return min; - - for (int ii=0; ii<valuesPtr->nValues; ii++) { - double x = valuesPtr->values[ii]; - // What do you do about negative values when using log - // scale values seems like a grey area. Mirror. - if (x < 0.0) - x = -x; - if ((x > minLimit) && (min > x)) - min = x; - } - if (min == DBL_MAX) - min = minLimit; - - return min; -} diff --git a/src/bltGrElem.h b/src/bltGrElem.h index 637071e..1c8b161 100644 --- a/src/bltGrElem.h +++ b/src/bltGrElem.h @@ -58,7 +58,7 @@ extern "C" { #define NORMALPEN(e) ((((e)->normalPenPtr == NULL) ? (e)->builtinPenPtr : (e)->normalPenPtr)) -typedef struct _Element Element; +class Element; typedef struct { Blt_VectorId vector; @@ -90,36 +90,6 @@ typedef struct { Pen* penPtr; } PenStyle; -typedef void (ElementDrawProc) (Graph *graphPtr, Drawable drawable, - Element* elemPtr); -typedef void (ElementToPostScriptProc) (Graph *graphPtr, Blt_Ps ps, - Element* elemPtr); -typedef void (ElementDestroyProc) (Graph *graphPtr, Element* elemPtr); -typedef int (ElementConfigProc) (Graph *graphPtr, Element* elemPtr); -typedef void (ElementMapProc) (Graph *graphPtr, Element* elemPtr); -typedef void (ElementExtentsProc) (Element* elemPtr, Region2d *extsPtr); -typedef void (ElementClosestProc) (Graph *graphPtr, Element* elemPtr); -typedef void (ElementDrawSymbolProc) (Graph *graphPtr, Drawable drawable, - Element* elemPtr, int x, int y, - int symbolSize); -typedef void (ElementSymbolToPostScriptProc) (Graph *graphPtr, Blt_Ps ps, - Element* elemPtr, double x, - double y, int symSize); - -typedef struct { - ElementClosestProc *closestProc; - ElementConfigProc *configProc; - ElementDestroyProc *destroyProc; - ElementDrawProc *drawActiveProc; - ElementDrawProc *drawNormalProc; - ElementDrawSymbolProc *drawSymbolProc; - ElementExtentsProc *extentsProc; - ElementToPostScriptProc *printActiveProc; - ElementToPostScriptProc *printNormalProc; - ElementSymbolToPostScriptProc *printSymbolProc; - ElementMapProc *mapProc; -} ElementProcs; - typedef struct { Element* elemPtr; const char* label; @@ -142,26 +112,49 @@ typedef struct { PenOptions builtinPen; } ElementOptions; -typedef struct _Element { +class Element { + public: GraphObj obj; + Graph* graphPtr_; unsigned int flags; - int hide; - Tcl_HashEntry *hashPtr; - void* ops; - - unsigned short row; - unsigned short col; - int *activeIndices; - int nActiveIndices; - ElementProcs *procsPtr; - Tk_OptionTable optionTable; - double xRange; - double yRange; + int hide_; + Tcl_HashEntry* hashPtr; + + unsigned short row_; + unsigned short col_; + int *activeIndices_; + int nActiveIndices_; + Tk_OptionTable optionTable_; + double xRange_; + double yRange_; Blt_ChainLink link; -} Element; -extern double Blt_FindElemValuesMinimum(ElemValues *vecPtr, double minLimit); + protected: + void* ops_; + + protected: + double FindElemValuesMinimum(ElemValues*, double); + PenStyle** StyleMap(); + + public: + Element(Graph*, const char*, Tcl_HashEntry*); + virtual ~Element(); + + virtual int configure() =0; + virtual void map() =0; + virtual void extents(Region2d*) =0; + virtual void drawActive(Drawable) =0; + virtual void drawNormal(Drawable) =0; + virtual void drawSymbol(Drawable, int, int, int) =0; + virtual void closest() =0; + virtual void printActive(Blt_Ps) =0; + virtual void printNormal(Blt_Ps) =0; + virtual void printSymbol(Blt_Ps, double, double, int) =0; + + void* ops() {return ops_;} + Tk_OptionTable optionTable() {return optionTable();} +}; + extern void Blt_FreeStylePalette (Blt_Chain stylePalette); -extern PenStyle** Blt_StyleMap (Element* elemPtr); #endif diff --git a/src/bltGrElemBar.C b/src/bltGrElemBar.C index 44c29ba..7e5db85 100644 --- a/src/bltGrElemBar.C +++ b/src/bltGrElemBar.C @@ -39,51 +39,6 @@ (((x0) <= (int)((r)->x + (r)->width - 1)) && ((x0) >= (int)(r)->x) && \ ((y0) <= (int)((r)->y + (r)->height - 1)) && ((y0) >= (int)(r)->y)) -typedef struct { - float x1, y1, x2, y2; -} BarRegion; - -typedef struct { - Weight weight; - BarPen* penPtr; - XRectangle *bars; - int nBars; - GraphSegments xeb; - GraphSegments yeb; - int symbolSize; - int errorBarCapWidth; -} BarStyle; - -// Defs - -static void ResetBar(BarElement* elemPtr); - -static ElementClosestProc ClosestBarProc; -static ElementConfigProc ConfigureBarProc; -static ElementDestroyProc DestroyBarProc; -static ElementDrawProc DrawActiveBarProc; -static ElementDrawProc DrawNormalBarProc; -static ElementDrawSymbolProc DrawSymbolProc; -static ElementExtentsProc GetBarExtentsProc; -static ElementToPostScriptProc ActiveBarToPostScriptProc; -static ElementToPostScriptProc NormalBarToPostScriptProc; -static ElementSymbolToPostScriptProc SymbolToPostScriptProc; -static ElementMapProc MapBarProc; - -static ElementProcs barProcs = { - ClosestBarProc, - ConfigureBarProc, - DestroyBarProc, - DrawActiveBarProc, - DrawNormalBarProc, - DrawSymbolProc, - GetBarExtentsProc, - ActiveBarToPostScriptProc, - NormalBarToPostScriptProc, - SymbolToPostScriptProc, - MapBarProc, -}; - // OptionSpecs static Tk_ObjCustomOption styleObjOption = @@ -213,56 +168,71 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, 0, 0, NULL, 0} }; -// Create - -Element* Blt_BarElement(Graph* graphPtr) +BarElement::BarElement(Graph* graphPtr, const char* name, Tcl_HashEntry* hPtr) + : Element(graphPtr, name, hPtr) { - BarElement* bePtr = (BarElement*)calloc(1, sizeof(BarElement)); - bePtr->ops = (BarElementOptions*)calloc(1, sizeof(BarElementOptions)); - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - ops->elemPtr = (Element*)bePtr; + Blt_GraphSetObjectClass(&obj, CID_ELEM_BAR); + + barToData_ =NULL; + bars_ =NULL; + activeToData_ =NULL; + activeRects_ =NULL; + nBars_ =0; + nActive_ =0; + xPad_ =0; + + xeb_.segments =NULL; + xeb_.length =0; + xeb_.map =NULL; + yeb_.segments =NULL; + yeb_.length =0; + yeb_.map =NULL; + + ops_ = (BarElementOptions*)calloc(1, sizeof(BarElementOptions)); + BarElementOptions* ops = (BarElementOptions*)ops_; + ops->elemPtr = (Element*)this; + + builtinPenPtr = new BarPen(graphPtr_, "builtin", &ops->builtinPen); + ops->builtinPenPtr = builtinPenPtr; - bePtr->procsPtr = &barProcs; - ops->builtinPenPtr = &bePtr->builtinPen; - - bePtr->builtinPen.init(graphPtr, "builtin", &ops->builtinPen); Tk_InitOptions(graphPtr->interp, (char*)&(ops->builtinPen), - bePtr->builtinPen.optionTable(), graphPtr->tkwin); + builtinPenPtr->optionTable(), graphPtr->tkwin); - bePtr->optionTable = Tk_CreateOptionTable(graphPtr->interp, optionSpecs); + optionTable_ = Tk_CreateOptionTable(graphPtr->interp, optionSpecs); - return (Element*)bePtr; + ops->stylePalette = Blt_Chain_Create(); + // this is an option and will be freed via Tk_FreeConfigOptions + // By default an element's name and label are the same + ops->label = Tcl_Alloc(strlen(name)+1); + if (name) + strcpy((char*)ops->label,(char*)name); } -static void DestroyBarProc(Graph* graphPtr, Element* elemPtr) +BarElement::~BarElement() { - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; if (ops->activePenPtr) Blt_FreePen((Pen*)ops->activePenPtr); if (ops->normalPenPtr) Blt_FreePen((Pen*)ops->normalPenPtr); + if (ops->builtinPenPtr) + delete builtinPenPtr; - ResetBar(bePtr); + ResetBar(); if (ops->stylePalette) { Blt_FreeStylePalette(ops->stylePalette); Blt_Chain_Destroy(ops->stylePalette); } - if (bePtr->activeIndices) - free(bePtr->activeIndices); } -// Configure - -static int ConfigureBarProc(Graph* graphPtr, Element* elemPtr) +int BarElement::configure() { - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; - if (bePtr->builtinPen.configure() != TCL_OK) + if (builtinPenPtr->configure() != TCL_OK) return TCL_ERROR; // Point to the static normal pen if no external pens have been selected. @@ -277,50 +247,234 @@ static int ConfigureBarProc(Graph* graphPtr, Element* elemPtr) return TCL_OK; } -// Support - -static void ResetStylePalette(Blt_Chain stylePalette) +void BarElement::map() { - for (Blt_ChainLink link = Blt_Chain_FirstLink(stylePalette); link; - link = Blt_Chain_NextLink(link)) { - BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); - stylePtr->xeb.length = 0; - stylePtr->yeb.length = 0; - stylePtr->nBars = 0; - } -} + BarElementOptions* ops = (BarElementOptions*)ops_; -static void CheckBarStacks(Graph* graphPtr, Axis2d *pairPtr, - double *minPtr, double *maxPtr) -{ - if ((graphPtr->barMode != BARS_STACKED) || (graphPtr->nBarGroups == 0)) + ResetBar(); + if (!ops->coords.x || !ops->coords.y || + !ops->coords.x->nValues || !ops->coords.y->nValues) return; + int nPoints = NUMBEROFPOINTS(ops); - BarGroup *gp, *gend; - for (gp = graphPtr->barGroups, gend = gp + graphPtr->nBarGroups; gp < gend; - gp++) { - if ((gp->axes.x == pairPtr->x) && (gp->axes.y == pairPtr->y)) { + // double barWidth = graphPtr->barWidth; + double barWidth = (ops->barWidth > 0.0f) ? + ops->barWidth : graphPtr_->barWidth; + double baseline = (ops->axes.y->logScale) ? 0.0 : graphPtr_->baseline; + double barOffset = barWidth * 0.5; - // Check if any of the y-values (because of stacking) are greater - // than the current limits of the graph. - if (gp->sum < 0.0f) { - if (*minPtr > gp->sum) - *minPtr = gp->sum; + // Create an array of bars representing the screen coordinates of all the + // segments in the bar. + XRectangle* bars = (XRectangle*)calloc(nPoints, sizeof(XRectangle)); + int* barToData = (int*)calloc(nPoints, sizeof(int)); + + double* x = ops->coords.x->values; + double* y = ops->coords.y->values; + int count = 0; + + int i; + XRectangle *rp; + for (rp = bars, i = 0; i < nPoints; i++) { + Point2d c1, c2; /* Two opposite corners of the rectangle + * in graph coordinates. */ + double dx, dy; + int height; + double right, left, top, bottom; + + if (((x[i] - barWidth) > ops->axes.x->axisRange.max) || + ((x[i] + barWidth) < ops->axes.x->axisRange.min)) { + continue; /* Abscissa is out of range of the + * x-axis */ + } + c1.x = x[i] - barOffset; + c1.y = y[i]; + c2.x = c1.x + barWidth; + c2.y = baseline; + + /* + * If the mode is "aligned" or "stacked" we need to adjust the x or y + * coordinates of the two corners. + */ + + if ((graphPtr_->nBarGroups > 0) && (graphPtr_->barMode != BARS_INFRONT) && + (!graphPtr_->stackAxes)) { + Tcl_HashEntry *hPtr; + BarSetKey key; + + key.value = (float)x[i]; + key.axes = ops->axes; + key.axes.y = NULL; + hPtr = Tcl_FindHashEntry(&graphPtr_->setTable, (char *)&key); + if (hPtr) { + + Tcl_HashTable *tablePtr = (Tcl_HashTable*)Tcl_GetHashValue(hPtr); + const char *name = (ops->groupName) ? + ops->groupName : ops->axes.y->obj.name; + hPtr = Tcl_FindHashEntry(tablePtr, name); + if (hPtr) { + double slice, width, offset; + + BarGroup *groupPtr = (BarGroup*)Tcl_GetHashValue(hPtr); + slice = barWidth / (double)graphPtr_->maxBarSetSize; + offset = (slice * groupPtr->index); + if (graphPtr_->maxBarSetSize > 1) { + offset += slice * 0.05; + slice *= 0.90; + } + switch (graphPtr_->barMode) { + case BARS_STACKED: + groupPtr->count++; + c2.y = groupPtr->lastY; + c1.y += c2.y; + groupPtr->lastY = c1.y; + c1.x += offset; + c2.x = c1.x + slice; + break; + + case BARS_ALIGNED: + slice /= groupPtr->nSegments; + c1.x += offset + (slice * groupPtr->count); + c2.x = c1.x + slice; + groupPtr->count++; + break; + + case BARS_OVERLAP: + slice /= (groupPtr->nSegments + 1); + width = slice + slice; + groupPtr->count++; + c1.x += offset + + (slice * (groupPtr->nSegments - groupPtr->count)); + c2.x = c1.x + width; + break; + + case BARS_INFRONT: + break; + } + } } - else { - if (*maxPtr < gp->sum) - *maxPtr = gp->sum; + } + int invertBar = 0; + if (c1.y < c2.y) { + double temp; + + /* Handle negative bar values by swapping ordinates */ + temp = c1.y, c1.y = c2.y, c2.y = temp; + invertBar = 1; + } + /* + * Get the two corners of the bar segment and compute the rectangle + */ + double ybot = c2.y; + c1 = Blt_Map2D(graphPtr_, c1.x, c1.y, &ops->axes); + c2 = Blt_Map2D(graphPtr_, c2.x, c2.y, &ops->axes); + if ((ybot == 0.0) && (ops->axes.y->logScale)) { + c2.y = graphPtr_->bottom; + } + + if (c2.y < c1.y) { + double t; + t = c1.y, c1.y = c2.y, c2.y = t; + } + if (c2.x < c1.x) { + double t; + t = c1.x, c1.x = c2.x, c2.x = t; + } + if ((c1.x > graphPtr_->right) || (c2.x < graphPtr_->left) || + (c1.y > graphPtr_->bottom) || (c2.y < graphPtr_->top)) { + continue; + } + /* Bound the bars horizontally by the width of the graph window */ + /* Bound the bars vertically by the position of the axis. */ + if (graphPtr_->stackAxes) { + top = ops->axes.y->screenMin; + bottom = ops->axes.y->screenMin + ops->axes.y->screenRange; + left = graphPtr_->left; + right = graphPtr_->right; + } else { + left = top = 0; + bottom = right = 10000; + /* Shouldn't really have a call to Tk_Width or Tk_Height in + * mapping routine. We only want to clamp the bar segment to the + * size of the window if we're actually mapped onscreen. */ + if (Tk_Height(graphPtr_->tkwin) > 1) { + bottom = Tk_Height(graphPtr_->tkwin); + } + if (Tk_Width(graphPtr_->tkwin) > 1) { + right = Tk_Width(graphPtr_->tkwin); } } + CLAMP(c1.y, top, bottom); + CLAMP(c2.y, top, bottom); + CLAMP(c1.x, left, right); + CLAMP(c2.x, left, right); + dx = fabs(c1.x - c2.x); + dy = fabs(c1.y - c2.y); + if ((dx == 0) || (dy == 0)) { + continue; + } + height = (int)dy; + if (invertBar) { + rp->y = (short int)MIN(c1.y, c2.y); + } else { + rp->y = (short int)(MAX(c1.y, c2.y)) - height; + } + rp->x = (short int)MIN(c1.x, c2.x); + rp->width = (short int)dx + 1; + rp->width |= 0x1; + if (rp->width < 1) { + rp->width = 1; + } + rp->height = height + 1; + if (rp->height < 1) { + rp->height = 1; + } + barToData[count] = i; /* Save the data index corresponding to + * the rectangle */ + count++; + rp++; } + nBars_ = count; + bars_ = bars; + barToData_ = barToData; + if (nActiveIndices_ > 0) { + MapActiveBars(); + } + + int size = 20; + if (count > 0) + size = bars->width; + + // Set the symbol size of all the pen styles + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; + link = Blt_Chain_NextLink(link)) { + BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); + BarPen* penPtr = stylePtr->penPtr; + BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); + stylePtr->symbolSize = size; + stylePtr->errorBarCapWidth = + (penOps->errorBarCapWidth > 0) + ? penOps->errorBarCapWidth : (size * 66666) / 100000; + stylePtr->errorBarCapWidth /= 2; + } + + BarStyle** dataToStyle = (BarStyle**)StyleMap(); + if (((ops->yHigh && ops->yHigh->nValues > 0) && + (ops->yLow && ops->yLow->nValues > 0)) || + ((ops->xHigh && ops->xHigh->nValues > 0) && + (ops->xLow && ops->xLow->nValues > 0)) || + (ops->xError && ops->xError->nValues > 0) || + (ops->yError && ops->yError->nValues > 0)) { + MapErrorBars(dataToStyle); + } + + MergePens(dataToStyle); + free(dataToStyle); } -static void GetBarExtentsProc(Element* elemPtr, Region2d *regPtr) +void BarElement::extents(Region2d *regPtr) { - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; - Graph* graphPtr = bePtr->obj.graphPtr; regPtr->top = regPtr->left = DBL_MAX; regPtr->bottom = regPtr->right = -DBL_MAX; @@ -329,7 +483,7 @@ static void GetBarExtentsProc(Element* elemPtr, Region2d *regPtr) return; int nPoints = NUMBEROFPOINTS(ops); - double barWidth = graphPtr->barWidth; + double barWidth = graphPtr_->barWidth; if (ops->barWidth > 0.0f) barWidth = ops->barWidth; @@ -339,18 +493,18 @@ static void GetBarExtentsProc(Element* elemPtr, Region2d *regPtr) regPtr->top = ops->coords.y->min; regPtr->bottom = ops->coords.y->max; - if (regPtr->bottom < graphPtr->baseline) - regPtr->bottom = graphPtr->baseline; + if (regPtr->bottom < graphPtr_->baseline) + regPtr->bottom = graphPtr_->baseline; // Handle stacked bar elements specially. // If element is stacked, the sum of its ordinates may be outside the // minimum/maximum limits of the element's data points. - if ((graphPtr->barMode == BARS_STACKED) && (graphPtr->nBarGroups > 0)) - CheckBarStacks(graphPtr, &ops->axes, ®Ptr->top, ®Ptr->bottom); + if ((graphPtr_->barMode == BARS_STACKED) && (graphPtr_->nBarGroups > 0)) + CheckBarStacks(&ops->axes, ®Ptr->top, ®Ptr->bottom); // Warning: You get what you deserve if the x-axis is logScale if (ops->axes.x->logScale) - regPtr->left = Blt_FindElemValuesMinimum(ops->coords.x, DBL_MIN) + middle; + regPtr->left = FindElemValuesMinimum(ops->coords.x, DBL_MIN) + middle; // Fix y-min limits for barchart if (ops->axes.y->logScale) { @@ -393,7 +547,7 @@ static void GetBarExtentsProc(Element* elemPtr, Region2d *regPtr) if (ops->xLow && (ops->xLow->nValues > 0)) { double left; if ((ops->xLow->min <= 0.0) && (ops->axes.x->logScale)) - left = Blt_FindElemValuesMinimum(ops->xLow, DBL_MIN); + left = FindElemValuesMinimum(ops->xLow, DBL_MIN); else left = ops->xLow->min; @@ -434,7 +588,7 @@ static void GetBarExtentsProc(Element* elemPtr, Region2d *regPtr) double top; if ((ops->yLow->min <= 0.0) && (ops->axes.y->logScale)) - top = Blt_FindElemValuesMinimum(ops->yLow, DBL_MIN); + top = FindElemValuesMinimum(ops->yLow, DBL_MIN); else top = ops->yLow->min; @@ -444,20 +598,19 @@ static void GetBarExtentsProc(Element* elemPtr, Region2d *regPtr) } } -static void ClosestBarProc(Graph* graphPtr, Element* elemPtr) +void BarElement::closest() { - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; - ClosestSearch* searchPtr = &graphPtr->search; + ClosestSearch* searchPtr = &graphPtr_->search; double minDist = searchPtr->dist; int imin = 0; int i; XRectangle *bp; - for (bp = bePtr->bars, i = 0; i < bePtr->nBars; i++, bp++) { + for (bp = bars_, i = 0; i < nBars_; i++, bp++) { if (PointInRectangle(bp, searchPtr->x, searchPtr->y)) { - imin = bePtr->barToData[i]; + imin = barToData_[i]; minDist = 0.0; break; } @@ -488,12 +641,12 @@ static void ClosestBarProc(Graph* graphPtr, Element* elemPtr) double dist = hypot((t.x - searchPtr->x), (t.y - searchPtr->y)); if (dist < minDist) { minDist = dist; - imin = bePtr->barToData[i]; + imin = barToData_[i]; } } } if (minDist < searchPtr->dist) { - searchPtr->elemPtr = (Element*)bePtr; + searchPtr->elemPtr = (Element*)this; searchPtr->dist = minDist; searchPtr->index = imin; searchPtr->point.x = @@ -503,209 +656,406 @@ static void ClosestBarProc(Graph* graphPtr, Element* elemPtr) } } -static void MergePens(BarElement* bePtr, BarStyle **dataToStyle) +void BarElement::drawActive(Drawable drawable) +{ + BarElementOptions* ops = (BarElementOptions*)ops_; + + if (ops->activePenPtr) { + BarPen* penPtr = ops->activePenPtr; + BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); + + if (nActiveIndices_ > 0) { + if (flags & ACTIVE_PENDING) { + MapActiveBars(); + } + DrawBarSegments(drawable, penPtr, activeRects_, nActive_); + if (penOps->valueShow != SHOW_NONE) + DrawBarValues(drawable, penPtr, activeRects_, nActive_, activeToData_); + } + else if (nActiveIndices_ < 0) { + DrawBarSegments(drawable, penPtr, bars_, nBars_); + if (penOps->valueShow != SHOW_NONE) + DrawBarValues(drawable, penPtr, bars_, nBars_, barToData_); + } + } +} + +void BarElement::drawNormal(Drawable drawable) +{ + BarElementOptions* ops = (BarElementOptions*)ops_; + + int count = 0; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; + link = Blt_Chain_NextLink(link)) { + + BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); + BarPen* penPtr = (BarPen*)stylePtr->penPtr; + BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); + + if (stylePtr->nBars > 0) + DrawBarSegments(drawable, penPtr, stylePtr->bars, stylePtr->nBars); + + if ((stylePtr->xeb.length > 0) && (penOps->errorBarShow & SHOW_X)) + Blt_Draw2DSegments(graphPtr_->display, drawable, penPtr->errorBarGC_, + stylePtr->xeb.segments, stylePtr->xeb.length); + + if ((stylePtr->yeb.length > 0) && (penOps->errorBarShow & SHOW_Y)) + Blt_Draw2DSegments(graphPtr_->display, drawable, penPtr->errorBarGC_, + stylePtr->yeb.segments, stylePtr->yeb.length); + + if (penOps->valueShow != SHOW_NONE) + DrawBarValues(drawable, penPtr, stylePtr->bars, stylePtr->nBars, + barToData_ + count); + + count += stylePtr->nBars; + } +} + +void BarElement::drawSymbol(Drawable drawable, int x, int y, int size) +{ + BarElementOptions* ops = (BarElementOptions*)ops_; + + BarPen* penPtr = NORMALPEN(ops); + BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); + + if (!penOps->fill && !penOps->outlineColor) + return; + + int radius = (size / 2); + size--; + + x -= radius; + y -= radius; + if (penPtr->fillGC_) + XSetTSOrigin(graphPtr_->display, penPtr->fillGC_, x, y); + + if (penOps->stipple != None) + XFillRectangle(graphPtr_->display, drawable, penPtr->fillGC_, x, y, + size, size); + else + Tk_Fill3DRectangle(graphPtr_->tkwin, drawable, penOps->fill, + x, y, size, size, penOps->borderWidth, penOps->relief); + + XDrawRectangle(graphPtr_->display, drawable, penPtr->outlineGC_, x, y, + size, size); + if (penPtr->fillGC_) + XSetTSOrigin(graphPtr_->display, penPtr->fillGC_, 0, 0); +} + +void BarElement::printActive(Blt_Ps ps) { - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; + + if (ops->activePenPtr) { + BarPen* penPtr = ops->activePenPtr; + BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); + + if (nActiveIndices_ > 0) { + if (flags & ACTIVE_PENDING) + MapActiveBars(); + SegmentsToPostScript(ps, penPtr, activeRects_, nActive_); + if (penOps->valueShow != SHOW_NONE) + BarValuesToPostScript(ps, penPtr, activeRects_, nActive_,activeToData_); + } + else if (nActiveIndices_ < 0) { + SegmentsToPostScript(ps, penPtr, bars_, nBars_); + if (penOps->valueShow != SHOW_NONE) + BarValuesToPostScript(ps, penPtr, bars_, nBars_, barToData_); + } + } +} + +void BarElement::printNormal(Blt_Ps ps) +{ + BarElementOptions* ops = (BarElementOptions*)ops_; + + int count = 0; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; + link = Blt_Chain_NextLink(link)) { + + BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); + BarPen* penPtr = (BarPen*)stylePtr->penPtr; + BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); + if (stylePtr->nBars > 0) + SegmentsToPostScript(ps, penPtr, stylePtr->bars, stylePtr->nBars); + + XColor* colorPtr = penOps->errorBarColor; + if (!colorPtr) + colorPtr = penOps->outlineColor; + + if ((stylePtr->xeb.length > 0) && (penOps->errorBarShow & SHOW_X)) { + Blt_Ps_XSetLineAttributes(ps, colorPtr, penOps->errorBarLineWidth, + NULL, CapButt, JoinMiter); + Blt_Ps_Draw2DSegments(ps, stylePtr->xeb.segments, + stylePtr->xeb.length); + } + + if ((stylePtr->yeb.length > 0) && (penOps->errorBarShow & SHOW_Y)) { + Blt_Ps_XSetLineAttributes(ps, colorPtr, penOps->errorBarLineWidth, + NULL, CapButt, JoinMiter); + Blt_Ps_Draw2DSegments(ps, stylePtr->yeb.segments, + stylePtr->yeb.length); + } + + if (penOps->valueShow != SHOW_NONE) + BarValuesToPostScript(ps, penPtr, stylePtr->bars, stylePtr->nBars, + barToData_ + count); + + count += stylePtr->nBars; + } +} + +void BarElement::printSymbol(Blt_Ps ps, double x, double y, int size) +{ + BarElementOptions* ops = (BarElementOptions*)ops_; + + BarPen* penPtr = NORMALPEN(ops); + BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); + + if (!penOps->fill && !penOps->outlineColor) + return; + + /* + * Build a PostScript procedure to draw the fill and outline of the symbol + * after the path of the symbol shape has been formed + */ + Blt_Ps_Append(ps, "\n" + "/DrawSymbolProc {\n" + "gsave\n "); + if (penOps->stipple != None) { + if (penOps->fill) { + Blt_Ps_XSetBackground(ps, Tk_3DBorderColor(penOps->fill)); + Blt_Ps_Append(ps, " gsave fill grestore\n "); + } + if (penOps->outlineColor) { + Blt_Ps_XSetForeground(ps, penOps->outlineColor); + } else { + Blt_Ps_XSetForeground(ps, Tk_3DBorderColor(penOps->fill)); + } + Blt_Ps_XSetStipple(ps, graphPtr_->display, penOps->stipple); + } else if (penOps->outlineColor) { + Blt_Ps_XSetForeground(ps, penOps->outlineColor); + Blt_Ps_Append(ps, " fill\n"); + } + Blt_Ps_Append(ps, " grestore\n"); + Blt_Ps_Append(ps, "} def\n\n"); + Blt_Ps_Format(ps, "%g %g %d Sq\n", x, y, size); +} + +// Support + +void BarElement::ResetStylePalette(Blt_Chain stylePalette) +{ + for (Blt_ChainLink link = Blt_Chain_FirstLink(stylePalette); link; + link = Blt_Chain_NextLink(link)) { + BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); + stylePtr->xeb.length = 0; + stylePtr->yeb.length = 0; + stylePtr->nBars = 0; + } +} + +void BarElement::CheckBarStacks(Axis2d *pairPtr, double *minPtr, double *maxPtr) +{ + if ((graphPtr_->barMode != BARS_STACKED) || (graphPtr_->nBarGroups == 0)) + return; + + BarGroup *gp, *gend; + for (gp = graphPtr_->barGroups, gend = gp + graphPtr_->nBarGroups; gp < gend; + gp++) { + if ((gp->axes.x == pairPtr->x) && (gp->axes.y == pairPtr->y)) { + + // Check if any of the y-values (because of stacking) are greater + // than the current limits of the graph. + if (gp->sum < 0.0f) { + if (*minPtr > gp->sum) + *minPtr = gp->sum; + } + else { + if (*maxPtr < gp->sum) + *maxPtr = gp->sum; + } + } + } +} + +void BarElement::MergePens(BarStyle** dataToStyle) +{ + BarElementOptions* ops = (BarElementOptions*)ops_; if (Blt_Chain_GetLength(ops->stylePalette) < 2) { Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); - stylePtr->nBars = bePtr->nBars; - stylePtr->bars = bePtr->bars; - stylePtr->symbolSize = bePtr->bars->width / 2; - stylePtr->xeb.length = bePtr->xeb.length; - stylePtr->xeb.segments = bePtr->xeb.segments; - stylePtr->yeb.length = bePtr->yeb.length; - stylePtr->yeb.segments = bePtr->yeb.segments; + stylePtr->nBars = nBars_; + stylePtr->bars = bars_; + stylePtr->symbolSize = bars_->width / 2; + stylePtr->xeb.length = xeb_.length; + stylePtr->xeb.segments = xeb_.segments; + stylePtr->yeb.length = yeb_.length; + stylePtr->yeb.segments = yeb_.segments; return; } // We have more than one style. Group bar segments of like pen styles // together - if (bePtr->nBars > 0) { - Blt_ChainLink link; - XRectangle *bars, *bp; - int *ip, *barToData; - - bars = (XRectangle*)malloc(bePtr->nBars * sizeof(XRectangle)); - barToData = (int*)malloc(bePtr->nBars * sizeof(int)); - bp = bars, ip = barToData; - for (link = Blt_Chain_FirstLink(ops->stylePalette); link; + if (nBars_ > 0) { + XRectangle* bars = (XRectangle*)malloc(nBars_ * sizeof(XRectangle)); + int* barToData = (int*)malloc(nBars_ * sizeof(int)); + XRectangle* bp = bars; + int* ip = barToData; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; link = Blt_Chain_NextLink(link)) { - int i; - BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); stylePtr->symbolSize = bp->width / 2; stylePtr->bars = bp; - for (i = 0; i < bePtr->nBars; i++) { - int iData; - - iData = bePtr->barToData[i]; + for (int ii=0; ii<nBars_; ii++) { + int iData = barToData[ii]; if (dataToStyle[iData] == stylePtr) { - *bp++ = bePtr->bars[i]; + *bp++ = bars[ii]; *ip++ = iData; } } stylePtr->nBars = bp - stylePtr->bars; } - free(bePtr->bars); - free(bePtr->barToData); - bePtr->bars = bars; - bePtr->barToData = barToData; + free(bars_); + free(barToData_); + bars_ = bars; + barToData_ = barToData; } - if (bePtr->xeb.length > 0) { - Blt_ChainLink link; - Segment2d *sp; - int *ip; - - Segment2d* bars = - (Segment2d*)malloc(bePtr->xeb.length * sizeof(Segment2d)); - int* map = (int*)malloc(bePtr->xeb.length * sizeof(int)); - sp = bars, ip = map; - for (link = Blt_Chain_FirstLink(ops->stylePalette); + if (xeb_.length > 0) { + Segment2d* bars = (Segment2d*)malloc(xeb_.length * sizeof(Segment2d)); + int* map = (int*)malloc(xeb_.length * sizeof(int)); + Segment2d *sp = bars; + int* ip = map; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; link = Blt_Chain_NextLink(link)) { - int i; - BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); stylePtr->xeb.segments = sp; - for (i = 0; i < bePtr->xeb.length; i++) { - int iData; - - iData = bePtr->xeb.map[i]; + for (int ii=0; ii<xeb_.length; ii++) { + int iData = xeb_.map[ii]; if (dataToStyle[iData] == stylePtr) { - *sp++ = bePtr->xeb.segments[i]; + *sp++ = xeb_.segments[ii]; *ip++ = iData; } } stylePtr->xeb.length = sp - stylePtr->xeb.segments; } - free(bePtr->xeb.segments); - bePtr->xeb.segments = bars; - free(bePtr->xeb.map); - bePtr->xeb.map = map; + free(xeb_.segments); + xeb_.segments = bars; + free(xeb_.map); + xeb_.map = map; } - if (bePtr->yeb.length > 0) { - Blt_ChainLink link; - Segment2d *sp; - int *ip; - - Segment2d* bars = - (Segment2d*)malloc(bePtr->yeb.length * sizeof(Segment2d)); - int* map = (int*)malloc(bePtr->yeb.length * sizeof(int)); - sp = bars, ip = map; - for (link = Blt_Chain_FirstLink(ops->stylePalette); link; - link = Blt_Chain_NextLink(link)) { - int i; + if (yeb_.length > 0) { + Segment2d* bars = (Segment2d*)malloc(yeb_.length * sizeof(Segment2d)); + int* map = (int*)malloc(yeb_.length * sizeof(int)); + Segment2d* sp = bars; + int* ip = map; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; + link = Blt_Chain_NextLink(link)) { BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); stylePtr->yeb.segments = sp; - for (i = 0; i < bePtr->yeb.length; i++) { - int iData; - - iData = bePtr->yeb.map[i]; + for (int ii=0; ii<yeb_.length; ii++) { + int iData = yeb_.map[ii]; if (dataToStyle[iData] == stylePtr) { - *sp++ = bePtr->yeb.segments[i]; + *sp++ = yeb_.segments[ii]; *ip++ = iData; } } stylePtr->yeb.length = sp - stylePtr->yeb.segments; } - free(bePtr->yeb.segments); - bePtr->yeb.segments = bars; - free(bePtr->yeb.map); - bePtr->yeb.map = map; + free(yeb_.segments); + yeb_.segments = bars; + free(yeb_.map); + yeb_.map = map; } } -static void MapActiveBars(BarElement* bePtr) +void BarElement::MapActiveBars() { - if (bePtr->activeRects) { - free(bePtr->activeRects); - bePtr->activeRects = NULL; + if (activeRects_) { + free(activeRects_); + activeRects_ = NULL; } - if (bePtr->activeToData) { - free(bePtr->activeToData); - bePtr->activeToData = NULL; + if (activeToData_) { + free(activeToData_); + activeToData_ = NULL; } - bePtr->nActive = 0; - - if (bePtr->nActiveIndices > 0) { - int i; - int count; + nActive_ = 0; + if (nActiveIndices_ > 0) { XRectangle *activeRects = - (XRectangle*)malloc(sizeof(XRectangle) * bePtr->nActiveIndices); - int* activeToData = (int*)malloc(sizeof(int) * bePtr->nActiveIndices); - count = 0; - for (i = 0; i < bePtr->nBars; i++) { + (XRectangle*)malloc(sizeof(XRectangle) * nActiveIndices_); + int* activeToData = (int*)malloc(sizeof(int) * nActiveIndices_); + int count = 0; + for (int ii=0; ii<nBars_; ii++) { int *ip, *iend; - - for (ip = bePtr->activeIndices, - iend = ip + bePtr->nActiveIndices; ip < iend; ip++) { - if (bePtr->barToData[i] == *ip) { - activeRects[count] = bePtr->bars[i]; - activeToData[count] = i; + for (ip = activeIndices_, iend = ip + nActiveIndices_; ip < iend; ip++) { + if (barToData_[ii] == *ip) { + activeRects[count] = bars_[ii]; + activeToData[count] = ii; count++; } } } - bePtr->nActive = count; - bePtr->activeRects = activeRects; - bePtr->activeToData = activeToData; + nActive_ = count; + activeRects_ = activeRects; + activeToData_ = activeToData; } - bePtr->flags &= ~ACTIVE_PENDING; + flags &= ~ACTIVE_PENDING; } -static void ResetBar(BarElement* bePtr) +void BarElement::ResetBar() { - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; ResetStylePalette(ops->stylePalette); - if (bePtr->activeRects) - free(bePtr->activeRects); + if (activeRects_) + free(activeRects_); + activeRects_ = NULL; - if (bePtr->activeToData) - free(bePtr->activeToData); + if (activeToData_) + free(activeToData_); + activeToData_ = NULL; - if (bePtr->xeb.segments) - free(bePtr->xeb.segments); + if (xeb_.segments) + free(xeb_.segments); + xeb_.segments = NULL; - if (bePtr->xeb.map) - free(bePtr->xeb.map); + if (xeb_.map) + free(xeb_.map); + xeb_.map = NULL; - if (bePtr->yeb.segments) - free(bePtr->yeb.segments); + if (yeb_.segments) + free(yeb_.segments); + yeb_.segments = NULL; - if (bePtr->yeb.map) - free(bePtr->yeb.map); + if (yeb_.map) + free(yeb_.map); + yeb_.map = NULL; - if (bePtr->bars) - free(bePtr->bars); + if (bars_) + free(bars_); + bars_ = NULL; - if (bePtr->barToData) - free(bePtr->barToData); + if (barToData_) + free(barToData_); + barToData_ = NULL; - bePtr->activeToData = bePtr->xeb.map = bePtr->yeb.map = - bePtr->barToData = NULL; - bePtr->activeRects = NULL; - bePtr->bars = NULL; - bePtr->xeb.segments = NULL; - bePtr->yeb.segments = NULL; - bePtr->nActive = 0; - bePtr->xeb.length = 0; - bePtr->yeb.length = 0; - bePtr->nBars = 0; + nActive_ = 0; + xeb_.length = 0; + yeb_.length = 0; + nBars_ = 0; } -static void MapErrorBars(Graph* graphPtr, BarElement* bePtr, - BarStyle **dataToStyle) +void BarElement::MapErrorBars(BarStyle **dataToStyle) { - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; Region2d reg; - Blt_GraphExtents(graphPtr, ®); + Blt_GraphExtents(graphPtr_, ®); int nPoints = NUMBEROFPOINTS(ops); int n =0; @@ -739,8 +1089,8 @@ static void MapErrorBars(Graph* graphPtr, BarElement* bePtr, low = ops->xLow ? ops->xLow->values[ii] : 0; } if ((isfinite(high)) && (isfinite(low))) { - Point2d p = Blt_Map2D(graphPtr, high, y, &ops->axes); - Point2d q = Blt_Map2D(graphPtr, low, y, &ops->axes); + Point2d p = Blt_Map2D(graphPtr_, high, y, &ops->axes); + Point2d q = Blt_Map2D(graphPtr_, low, y, &ops->axes); segPtr->p = p; segPtr->q = q; if (Blt_LineRectClip(®, &segPtr->p, &segPtr->q)) { @@ -766,9 +1116,9 @@ static void MapErrorBars(Graph* graphPtr, BarElement* bePtr, } } } - bePtr->xeb.segments = bars; - bePtr->xeb.length = segPtr - bars; - bePtr->xeb.map = map; + xeb_.segments = bars; + xeb_.length = segPtr - bars; + xeb_.map = map; } n =0; @@ -801,8 +1151,8 @@ static void MapErrorBars(Graph* graphPtr, BarElement* bePtr, low = ops->yLow->values[ii]; } if ((isfinite(high)) && (isfinite(low))) { - Point2d p = Blt_Map2D(graphPtr, x, high, &ops->axes); - Point2d q = Blt_Map2D(graphPtr, x, low, &ops->axes); + Point2d p = Blt_Map2D(graphPtr_, x, high, &ops->axes); + Point2d q = Blt_Map2D(graphPtr_, x, low, &ops->axes); segPtr->p = p; segPtr->q = q; if (Blt_LineRectClip(®, &segPtr->p, &segPtr->q)) { @@ -828,278 +1178,17 @@ static void MapErrorBars(Graph* graphPtr, BarElement* bePtr, } } } - bePtr->yeb.segments = bars; - bePtr->yeb.length = segPtr - bars; - bePtr->yeb.map = map; - } -} - -static void MapBarProc(Graph* graphPtr, Element* elemPtr) -{ - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - - ResetBar(bePtr); - if (!ops->coords.x || !ops->coords.y || - !ops->coords.x->nValues || !ops->coords.y->nValues) - return; - int nPoints = NUMBEROFPOINTS(ops); - - // double barWidth = graphPtr->barWidth; - double barWidth = (ops->barWidth > 0.0f) ? - ops->barWidth : graphPtr->barWidth; - double baseline = (ops->axes.y->logScale) ? 0.0 : graphPtr->baseline; - double barOffset = barWidth * 0.5; - - // Create an array of bars representing the screen coordinates of all the - // segments in the bar. - XRectangle* bars = (XRectangle*)calloc(nPoints, sizeof(XRectangle)); - int* barToData = (int*)calloc(nPoints, sizeof(int)); - - double* x = ops->coords.x->values; - double* y = ops->coords.y->values; - int count = 0; - - int i; - XRectangle *rp; - for (rp = bars, i = 0; i < nPoints; i++) { - Point2d c1, c2; /* Two opposite corners of the rectangle - * in graph coordinates. */ - double dx, dy; - int height; - double right, left, top, bottom; - - if (((x[i] - barWidth) > ops->axes.x->axisRange.max) || - ((x[i] + barWidth) < ops->axes.x->axisRange.min)) { - continue; /* Abscissa is out of range of the - * x-axis */ - } - c1.x = x[i] - barOffset; - c1.y = y[i]; - c2.x = c1.x + barWidth; - c2.y = baseline; - - /* - * If the mode is "aligned" or "stacked" we need to adjust the x or y - * coordinates of the two corners. - */ - - if ((graphPtr->nBarGroups > 0) && (graphPtr->barMode != BARS_INFRONT) && - (!graphPtr->stackAxes)) { - Tcl_HashEntry *hPtr; - BarSetKey key; - - key.value = (float)x[i]; - key.axes = ops->axes; - key.axes.y = NULL; - hPtr = Tcl_FindHashEntry(&graphPtr->setTable, (char *)&key); - if (hPtr) { - - Tcl_HashTable *tablePtr = (Tcl_HashTable*)Tcl_GetHashValue(hPtr); - const char *name = (ops->groupName) ? - ops->groupName : ops->axes.y->obj.name; - hPtr = Tcl_FindHashEntry(tablePtr, name); - if (hPtr) { - double slice, width, offset; - - BarGroup *groupPtr = (BarGroup*)Tcl_GetHashValue(hPtr); - slice = barWidth / (double)graphPtr->maxBarSetSize; - offset = (slice * groupPtr->index); - if (graphPtr->maxBarSetSize > 1) { - offset += slice * 0.05; - slice *= 0.90; - } - switch (graphPtr->barMode) { - case BARS_STACKED: - groupPtr->count++; - c2.y = groupPtr->lastY; - c1.y += c2.y; - groupPtr->lastY = c1.y; - c1.x += offset; - c2.x = c1.x + slice; - break; - - case BARS_ALIGNED: - slice /= groupPtr->nSegments; - c1.x += offset + (slice * groupPtr->count); - c2.x = c1.x + slice; - groupPtr->count++; - break; - - case BARS_OVERLAP: - slice /= (groupPtr->nSegments + 1); - width = slice + slice; - groupPtr->count++; - c1.x += offset + - (slice * (groupPtr->nSegments - groupPtr->count)); - c2.x = c1.x + width; - break; - - case BARS_INFRONT: - break; - } - } - } - } - int invertBar = 0; - if (c1.y < c2.y) { - double temp; - - /* Handle negative bar values by swapping ordinates */ - temp = c1.y, c1.y = c2.y, c2.y = temp; - invertBar = 1; - } - /* - * Get the two corners of the bar segment and compute the rectangle - */ - double ybot = c2.y; - c1 = Blt_Map2D(graphPtr, c1.x, c1.y, &ops->axes); - c2 = Blt_Map2D(graphPtr, c2.x, c2.y, &ops->axes); - if ((ybot == 0.0) && (ops->axes.y->logScale)) { - c2.y = graphPtr->bottom; - } - - if (c2.y < c1.y) { - double t; - t = c1.y, c1.y = c2.y, c2.y = t; - } - if (c2.x < c1.x) { - double t; - t = c1.x, c1.x = c2.x, c2.x = t; - } - if ((c1.x > graphPtr->right) || (c2.x < graphPtr->left) || - (c1.y > graphPtr->bottom) || (c2.y < graphPtr->top)) { - continue; - } - /* Bound the bars horizontally by the width of the graph window */ - /* Bound the bars vertically by the position of the axis. */ - if (graphPtr->stackAxes) { - top = ops->axes.y->screenMin; - bottom = ops->axes.y->screenMin + ops->axes.y->screenRange; - left = graphPtr->left; - right = graphPtr->right; - } else { - left = top = 0; - bottom = right = 10000; - /* Shouldn't really have a call to Tk_Width or Tk_Height in - * mapping routine. We only want to clamp the bar segment to the - * size of the window if we're actually mapped onscreen. */ - if (Tk_Height(graphPtr->tkwin) > 1) { - bottom = Tk_Height(graphPtr->tkwin); - } - if (Tk_Width(graphPtr->tkwin) > 1) { - right = Tk_Width(graphPtr->tkwin); - } - } - CLAMP(c1.y, top, bottom); - CLAMP(c2.y, top, bottom); - CLAMP(c1.x, left, right); - CLAMP(c2.x, left, right); - dx = fabs(c1.x - c2.x); - dy = fabs(c1.y - c2.y); - if ((dx == 0) || (dy == 0)) { - continue; - } - height = (int)dy; - if (invertBar) { - rp->y = (short int)MIN(c1.y, c2.y); - } else { - rp->y = (short int)(MAX(c1.y, c2.y)) - height; - } - rp->x = (short int)MIN(c1.x, c2.x); - rp->width = (short int)dx + 1; - rp->width |= 0x1; - if (rp->width < 1) { - rp->width = 1; - } - rp->height = height + 1; - if (rp->height < 1) { - rp->height = 1; - } - barToData[count] = i; /* Save the data index corresponding to - * the rectangle */ - count++; - rp++; - } - bePtr->nBars = count; - bePtr->bars = bars; - bePtr->barToData = barToData; - if (bePtr->nActiveIndices > 0) { - MapActiveBars(bePtr); - } - - int size = 20; - if (count > 0) - size = bars->width; - - // Set the symbol size of all the pen styles - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; - link = Blt_Chain_NextLink(link)) { - BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); - BarPen* penPtr = stylePtr->penPtr; - BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - stylePtr->symbolSize = size; - stylePtr->errorBarCapWidth = - (penOps->errorBarCapWidth > 0) - ? penOps->errorBarCapWidth : (size * 66666) / 100000; - stylePtr->errorBarCapWidth /= 2; - } - - BarStyle** dataToStyle = (BarStyle**)Blt_StyleMap((Element*)bePtr); - if (((ops->yHigh && ops->yHigh->nValues > 0) && - (ops->yLow && ops->yLow->nValues > 0)) || - ((ops->xHigh && ops->xHigh->nValues > 0) && - (ops->xLow && ops->xLow->nValues > 0)) || - (ops->xError && ops->xError->nValues > 0) || - (ops->yError && ops->yError->nValues > 0)) { - MapErrorBars(graphPtr, bePtr, dataToStyle); + yeb_.segments = bars; + yeb_.length = segPtr - bars; + yeb_.map = map; } - - MergePens(bePtr, dataToStyle); - free(dataToStyle); -} - -static void DrawSymbolProc(Graph* graphPtr, Drawable drawable, - Element* elemPtr, int x, int y, int size) -{ - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - - BarPen* penPtr = NORMALPEN(ops); - BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - - if (!penOps->fill && !penOps->outlineColor) - return; - - int radius = (size / 2); - size--; - - x -= radius; - y -= radius; - if (penPtr->fillGC_) - XSetTSOrigin(graphPtr->display, penPtr->fillGC_, x, y); - - if (penOps->stipple != None) - XFillRectangle(graphPtr->display, drawable, penPtr->fillGC_, x, y, - size, size); - else - Tk_Fill3DRectangle(graphPtr->tkwin, drawable, penOps->fill, - x, y, size, size, penOps->borderWidth, penOps->relief); - - XDrawRectangle(graphPtr->display, drawable, penPtr->outlineGC_, x, y, - size, size); - if (penPtr->fillGC_) - XSetTSOrigin(graphPtr->display, penPtr->fillGC_, 0, 0); } -static void SetBackgroundClipRegion(Tk_Window tkwin, Tk_3DBorder border, - TkRegion rgn) +void BarElement::SetBackgroundClipRegion(Tk_Window tkwin, Tk_3DBorder border, + TkRegion rgn) { - Display *display; - GC gc; - - display = Tk_Display(tkwin); - gc = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); + Display* display = Tk_Display(tkwin); + GC gc = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); TkSetRegion(display, gc, rgn); gc = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); TkSetRegion(display, gc, rgn); @@ -1107,13 +1196,10 @@ static void SetBackgroundClipRegion(Tk_Window tkwin, Tk_3DBorder border, TkSetRegion(display, gc, rgn); } -static void UnsetBackgroundClipRegion(Tk_Window tkwin, Tk_3DBorder border) +void BarElement::UnsetBackgroundClipRegion(Tk_Window tkwin, Tk_3DBorder border) { - Display *display; - GC gc; - - display = Tk_Display(tkwin); - gc = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); + Display* display = Tk_Display(tkwin); + GC gc = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); XSetClipMask(display, gc, None); gc = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); XSetClipMask(display, gc, None); @@ -1121,17 +1207,17 @@ static void UnsetBackgroundClipRegion(Tk_Window tkwin, Tk_3DBorder border) XSetClipMask(display, gc, None); } -static void DrawBarSegments(Graph* graphPtr, Drawable drawable, BarPen* penPtr, - XRectangle *bars, int nBars) +void BarElement::DrawBarSegments(Drawable drawable, BarPen* penPtr, + XRectangle *bars, int nBars) { BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); TkRegion rgn; XRectangle clip; - clip.x = graphPtr->left; - clip.y = graphPtr->top; - clip.width = graphPtr->right - graphPtr->left + 1; - clip.height = graphPtr->bottom - graphPtr->top + 1; + clip.x = graphPtr_->left; + clip.y = graphPtr_->top; + clip.width = graphPtr_->right - graphPtr_->left + 1; + clip.height = graphPtr_->bottom - graphPtr_->top + 1; rgn = TkCreateRegion(); TkUnionRectWithRegion(&clip, rgn, rgn); @@ -1141,53 +1227,51 @@ static void DrawBarSegments(Graph* graphPtr, Drawable drawable, BarPen* penPtr, int hasOutline = ((relief == TK_RELIEF_FLAT) && penOps->outlineColor); if (penOps->stipple != None) - TkSetRegion(graphPtr->display, penPtr->fillGC_, rgn); + TkSetRegion(graphPtr_->display, penPtr->fillGC_, rgn); - SetBackgroundClipRegion(graphPtr->tkwin, penOps->fill, rgn); + SetBackgroundClipRegion(graphPtr_->tkwin, penOps->fill, rgn); if (hasOutline) - TkSetRegion(graphPtr->display, penPtr->outlineGC_, rgn); + TkSetRegion(graphPtr_->display, penPtr->outlineGC_, rgn); XRectangle *rp, *rend; for (rp = bars, rend = rp + nBars; rp < rend; rp++) { if (penOps->stipple != None) - XFillRectangle(graphPtr->display, drawable, penPtr->fillGC_, + XFillRectangle(graphPtr_->display, drawable, penPtr->fillGC_, rp->x, rp->y, rp->width, rp->height); else - Tk_Fill3DRectangle(graphPtr->tkwin, drawable, + Tk_Fill3DRectangle(graphPtr_->tkwin, drawable, penOps->fill, rp->x, rp->y, rp->width, rp->height, penOps->borderWidth, relief); if (hasOutline) - XDrawRectangle(graphPtr->display, drawable, penPtr->outlineGC_, + XDrawRectangle(graphPtr_->display, drawable, penPtr->outlineGC_, rp->x, rp->y, rp->width, rp->height); } - UnsetBackgroundClipRegion(graphPtr->tkwin, penOps->fill); + UnsetBackgroundClipRegion(graphPtr_->tkwin, penOps->fill); if (hasOutline) - XSetClipMask(graphPtr->display, penPtr->outlineGC_, None); + XSetClipMask(graphPtr_->display, penPtr->outlineGC_, None); if (penOps->stipple != None) - XSetClipMask(graphPtr->display, penPtr->fillGC_, None); + XSetClipMask(graphPtr_->display, penPtr->fillGC_, None); } else if (penOps->outlineColor) { - TkSetRegion(graphPtr->display, penPtr->outlineGC_, rgn); - XDrawRectangles(graphPtr->display, drawable, penPtr->outlineGC_, bars, + TkSetRegion(graphPtr_->display, penPtr->outlineGC_, rgn); + XDrawRectangles(graphPtr_->display, drawable, penPtr->outlineGC_, bars, nBars); - XSetClipMask(graphPtr->display, penPtr->outlineGC_, None); + XSetClipMask(graphPtr_->display, penPtr->outlineGC_, None); } TkDestroyRegion(rgn); } -static void DrawBarValues(Graph* graphPtr, Drawable drawable, - BarElement* bePtr, - BarPen* penPtr, XRectangle *bars, int nBars, - int *barToData) +void BarElement::DrawBarValues(Drawable drawable, BarPen* penPtr, + XRectangle *bars, int nBars, int *barToData) { - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); const char *fmt = penOps->valueFormat; @@ -1214,132 +1298,25 @@ static void DrawBarValues(Graph* graphPtr, Drawable drawable, sprintf_s(string + strlen(string), TCL_DOUBLE_SPACE, fmt, y); } - if (graphPtr->inverted) { + if (graphPtr_->inverted) { anchorPos.y = rp->y + rp->height * 0.5; anchorPos.x = rp->x + rp->width; - if (x < graphPtr->baseline) + if (x < graphPtr_->baseline) anchorPos.x -= rp->width; } else { anchorPos.x = rp->x + rp->width * 0.5; anchorPos.y = rp->y; - if (y < graphPtr->baseline) + if (y < graphPtr_->baseline) anchorPos.y += rp->height; } - Blt_DrawText(graphPtr->tkwin, drawable, string, &penOps->valueStyle, + Blt_DrawText(graphPtr_->tkwin, drawable, string, &penOps->valueStyle, (int)anchorPos.x, (int)anchorPos.y); } } -static void DrawNormalBarProc(Graph* graphPtr, Drawable drawable, - Element* elemPtr) -{ - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - - int count = 0; - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; - link = Blt_Chain_NextLink(link)) { - - BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); - BarPen* penPtr = (BarPen*)stylePtr->penPtr; - BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - - if (stylePtr->nBars > 0) - DrawBarSegments(graphPtr, drawable, penPtr, stylePtr->bars, - stylePtr->nBars); - - if ((stylePtr->xeb.length > 0) && (penOps->errorBarShow & SHOW_X)) - Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC_, - stylePtr->xeb.segments, stylePtr->xeb.length); - - if ((stylePtr->yeb.length > 0) && (penOps->errorBarShow & SHOW_Y)) - Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC_, - stylePtr->yeb.segments, stylePtr->yeb.length); - - if (penOps->valueShow != SHOW_NONE) - DrawBarValues(graphPtr, drawable, bePtr, penPtr, - stylePtr->bars, stylePtr->nBars, - bePtr->barToData + count); - - count += stylePtr->nBars; - } -} - -static void DrawActiveBarProc(Graph* graphPtr, Drawable drawable, - Element* elemPtr) -{ - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - - if (ops->activePenPtr) { - BarPen* penPtr = ops->activePenPtr; - BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - - if (bePtr->nActiveIndices > 0) { - if (bePtr->flags & ACTIVE_PENDING) { - MapActiveBars(bePtr); - } - DrawBarSegments(graphPtr, drawable, penPtr, bePtr->activeRects, - bePtr->nActive); - if (penOps->valueShow != SHOW_NONE) { - DrawBarValues(graphPtr, drawable, bePtr, penPtr, - bePtr->activeRects, bePtr->nActive, - bePtr->activeToData); - } - } - else if (bePtr->nActiveIndices < 0) { - DrawBarSegments(graphPtr, drawable, penPtr, bePtr->bars, - bePtr->nBars); - if (penOps->valueShow != SHOW_NONE) { - DrawBarValues(graphPtr, drawable, bePtr, penPtr, - bePtr->bars, bePtr->nBars, bePtr->barToData); - } - } - } -} - -static void SymbolToPostScriptProc(Graph* graphPtr, Blt_Ps ps, Element* elemPtr, - double x, double y, int size) -{ - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - - BarPen* penPtr = NORMALPEN(ops); - BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - - if (!penOps->fill && !penOps->outlineColor) - return; - - /* - * Build a PostScript procedure to draw the fill and outline of the symbol - * after the path of the symbol shape has been formed - */ - Blt_Ps_Append(ps, "\n" - "/DrawSymbolProc {\n" - "gsave\n "); - if (penOps->stipple != None) { - if (penOps->fill) { - Blt_Ps_XSetBackground(ps, Tk_3DBorderColor(penOps->fill)); - Blt_Ps_Append(ps, " gsave fill grestore\n "); - } - if (penOps->outlineColor) { - Blt_Ps_XSetForeground(ps, penOps->outlineColor); - } else { - Blt_Ps_XSetForeground(ps, Tk_3DBorderColor(penOps->fill)); - } - Blt_Ps_XSetStipple(ps, graphPtr->display, penOps->stipple); - } else if (penOps->outlineColor) { - Blt_Ps_XSetForeground(ps, penOps->outlineColor); - Blt_Ps_Append(ps, " fill\n"); - } - Blt_Ps_Append(ps, " grestore\n"); - Blt_Ps_Append(ps, "} def\n\n"); - Blt_Ps_Format(ps, "%g %g %d Sq\n", x, y, size); -} - -static void SegmentsToPostScript(Graph* graphPtr, Blt_Ps ps, BarPen* penPtr, - XRectangle *bars, int nBars) +void BarElement::SegmentsToPostScript(Blt_Ps ps, BarPen* penPtr, + XRectangle *bars, int nBars) { BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); XRectangle *rp, *rend; @@ -1362,7 +1339,7 @@ static void SegmentsToPostScript(Graph* graphPtr, Blt_Ps ps, BarPen* penPtr, } else { Blt_Ps_XSetForeground(ps, Tk_3DBorderColor(penOps->fill)); } - Blt_Ps_XSetStipple(ps, graphPtr->display, penOps->stipple); + Blt_Ps_XSetStipple(ps, graphPtr_->display, penOps->stipple); } else if (penOps->outlineColor) { Blt_Ps_XSetForeground(ps, penOps->outlineColor); Blt_Ps_XFillRectangle(ps, (double)rp->x, (double)rp->y, @@ -1377,13 +1354,12 @@ static void SegmentsToPostScript(Graph* graphPtr, Blt_Ps ps, BarPen* penPtr, } } -static void BarValuesToPostScript(Graph* graphPtr, Blt_Ps ps, - BarElement* bePtr, - BarPen* penPtr, XRectangle *bars, int nBars, - int *barToData) +void BarElement::BarValuesToPostScript(Blt_Ps ps, BarPen* penPtr, + XRectangle *bars, int nBars, + int *barToData) { BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; + BarElementOptions* ops = (BarElementOptions*)ops_; XRectangle *rp, *rend; char string[TCL_DOUBLE_SPACE * 2 + 2]; @@ -1408,16 +1384,16 @@ static void BarValuesToPostScript(Graph* graphPtr, Blt_Ps ps, strcat(string, ","); sprintf_s(string + strlen(string), TCL_DOUBLE_SPACE, fmt, y); } - if (graphPtr->inverted) { + if (graphPtr_->inverted) { anchorPos.y = rp->y + rp->height * 0.5; anchorPos.x = rp->x + rp->width; - if (x < graphPtr->baseline) { + if (x < graphPtr_->baseline) { anchorPos.x -= rp->width; } } else { anchorPos.x = rp->x + rp->width * 0.5; anchorPos.y = rp->y; - if (y < graphPtr->baseline) { + if (y < graphPtr_->baseline) { anchorPos.y += rp->height; } } @@ -1426,80 +1402,7 @@ static void BarValuesToPostScript(Graph* graphPtr, Blt_Ps ps, } } -static void ActiveBarToPostScriptProc(Graph* graphPtr, Blt_Ps ps, - Element* elemPtr) -{ - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - - if (ops->activePenPtr) { - BarPen* penPtr = ops->activePenPtr; - BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - - if (bePtr->nActiveIndices > 0) { - if (bePtr->flags & ACTIVE_PENDING) { - MapActiveBars(bePtr); - } - SegmentsToPostScript(graphPtr, ps, penPtr, bePtr->activeRects, - bePtr->nActive); - if (penOps->valueShow != SHOW_NONE) { - BarValuesToPostScript(graphPtr, ps, bePtr, penPtr, - bePtr->activeRects, bePtr->nActive, bePtr->activeToData); - } - } else if (bePtr->nActiveIndices < 0) { - SegmentsToPostScript(graphPtr, ps, penPtr, bePtr->bars, - bePtr->nBars); - if (penOps->valueShow != SHOW_NONE) { - BarValuesToPostScript(graphPtr, ps, bePtr, penPtr, - bePtr->bars, bePtr->nBars, bePtr->barToData); - } - } - } -} - -static void NormalBarToPostScriptProc(Graph* graphPtr, Blt_Ps ps, - Element* elemPtr) -{ - BarElement* bePtr = (BarElement*)elemPtr; - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - - int count = 0; - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; - link = Blt_Chain_NextLink(link)) { - - BarStyle *stylePtr = (BarStyle*)Blt_Chain_GetValue(link); - BarPen* penPtr = (BarPen*)stylePtr->penPtr; - BarPenOptions* penOps = (BarPenOptions*)penPtr->ops(); - if (stylePtr->nBars > 0) - SegmentsToPostScript(graphPtr, ps, penPtr, stylePtr->bars, - stylePtr->nBars); - - XColor* colorPtr = penOps->errorBarColor; - if (!colorPtr) - colorPtr = penOps->outlineColor; - - if ((stylePtr->xeb.length > 0) && (penOps->errorBarShow & SHOW_X)) { - Blt_Ps_XSetLineAttributes(ps, colorPtr, penOps->errorBarLineWidth, - NULL, CapButt, JoinMiter); - Blt_Ps_Draw2DSegments(ps, stylePtr->xeb.segments, - stylePtr->xeb.length); - } - - if ((stylePtr->yeb.length > 0) && (penOps->errorBarShow & SHOW_Y)) { - Blt_Ps_XSetLineAttributes(ps, colorPtr, penOps->errorBarLineWidth, - NULL, CapButt, JoinMiter); - Blt_Ps_Draw2DSegments(ps, stylePtr->yeb.segments, - stylePtr->yeb.length); - } - - if (penOps->valueShow != SHOW_NONE) - BarValuesToPostScript(graphPtr, ps, bePtr, penPtr, - stylePtr->bars, stylePtr->nBars, - bePtr->barToData + count); - - count += stylePtr->nBars; - } -} +// External void Blt_InitBarSetTable(Graph* graphPtr) { @@ -1532,8 +1435,8 @@ void Blt_InitBarSetTable(Graph* graphPtr) int nPoints; BarElement* bePtr = (BarElement*)Blt_Chain_GetValue(link); - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - if ((bePtr->hide) || (bePtr->obj.classId != CID_ELEM_BAR)) + BarElementOptions* ops = (BarElementOptions*)bePtr->ops(); + if ((bePtr->hide_) || (bePtr->obj.classId != CID_ELEM_BAR)) continue; nSegs++; @@ -1651,8 +1554,8 @@ void Blt_ComputeBarStacks(Graph* graphPtr) double *x, *y, *xend; BarElement* bePtr = (BarElement*)Blt_Chain_GetValue(link); - BarElementOptions* ops = (BarElementOptions*)bePtr->ops; - if ((bePtr->hide) || (bePtr->obj.classId != CID_ELEM_BAR)) + BarElementOptions* ops = (BarElementOptions*)bePtr->ops(); + if ((bePtr->hide_) || (bePtr->obj.classId != CID_ELEM_BAR)) continue; if (ops->coords.x && ops->coords.y) { diff --git a/src/bltGrElemBar.h b/src/bltGrElemBar.h index cbe044c..c998484 100644 --- a/src/bltGrElemBar.h +++ b/src/bltGrElemBar.h @@ -39,6 +39,21 @@ using namespace std; #include "bltGrPenBar.h" typedef struct { + float x1, y1, x2, y2; +} BarRegion; + +typedef struct { + Weight weight; + BarPen* penPtr; + XRectangle *bars; + int nBars; + GraphSegments xeb; + GraphSegments yeb; + int symbolSize; + int errorBarCapWidth; +} BarStyle; + +typedef struct { Element* elemPtr; const char *label; char** tags; @@ -64,34 +79,51 @@ typedef struct { const char *groupName; } BarElementOptions; -typedef struct { - GraphObj obj; - unsigned int flags; - int hide; - Tcl_HashEntry *hashPtr; - void* ops; +class BarElement : public Element { + public: + BarPen* builtinPenPtr; + int* barToData_; + XRectangle* bars_; + int* activeToData_; + XRectangle* activeRects_; + int nBars_; + int nActive_; + int xPad_; + GraphSegments xeb_; + GraphSegments yeb_; - unsigned short row; - unsigned short col; - int *activeIndices; - int nActiveIndices; - ElementProcs *procsPtr; - Tk_OptionTable optionTable; - double xRange; - double yRange; - Blt_ChainLink link; + void ResetStylePalette(Blt_Chain); + void CheckBarStacks(Axis2d*, double*, double*); + void MergePens(BarStyle**); + void MapActiveBars(); + void ResetBar(); + void MapErrorBars(BarStyle**); + void SetBackgroundClipRegion(Tk_Window, Tk_3DBorder, TkRegion); + void UnsetBackgroundClipRegion(Tk_Window, Tk_3DBorder); + void DrawBarSegments(Drawable, BarPen*, XRectangle*, int); + void DrawBarValues(Drawable, BarPen*, XRectangle*, int, int*); + void SegmentsToPostScript(Blt_Ps, BarPen*, XRectangle*, int); + void BarValuesToPostScript(Blt_Ps, BarPen*, XRectangle*, int, int*); - // Fields specific to Bar Element - BarPen builtinPen; - int *barToData; - XRectangle *bars; - int *activeToData; - XRectangle *activeRects; - int nBars; - int nActive; - int xPad; - GraphSegments xeb; - GraphSegments yeb; -} BarElement; + public: + BarElement(Graph*, const char*, Tcl_HashEntry*); + virtual ~BarElement(); + + int configure(); + void map(); + void extents(Region2d*); + void closest(); + void drawActive(Drawable); + void drawNormal(Drawable); + void drawSymbol(Drawable, int, int, int); + void printActive(Blt_Ps); + void printNormal(Blt_Ps); + void printSymbol(Blt_Ps, double, double, int); +}; + +extern void Blt_InitBarSetTable(Graph* graphPtr); +extern void Blt_ComputeBarStacks(Graph* graphPtr); +extern void Blt_ResetBarGroups(Graph* graphPtr); +extern void Blt_DestroyBarSets(Graph* graphPtr); #endif diff --git a/src/bltGrElemLine.C b/src/bltGrElemLine.C index 79ac361..54eba89 100644 --- a/src/bltGrElemLine.C +++ b/src/bltGrElemLine.C @@ -61,72 +61,9 @@ extern "C" { #define DRAW_SYMBOL(linePtr) \ (((linePtr)->symbolCounter % (linePtr)->symbolInterval) == 0) -typedef enum { - PEN_INCREASING, PEN_DECREASING, PEN_BOTH_DIRECTIONS -} PenDirection; - -typedef struct { - Point2d *screenPts; - int nScreenPts; - int *styleMap; - int *map; -} MapInfo; - -typedef struct { - int start; - GraphPoints screenPts; -} bltTrace; - -typedef struct { - Weight weight; - LinePen* penPtr; - GraphPoints symbolPts; - GraphSegments lines; - GraphSegments xeb; - GraphSegments yeb; - int symbolSize; - int errorBarCapWidth; -} LineStyle; - // Defs -typedef double (DistanceProc)(int x, int y, Point2d *p, Point2d *q, Point2d *t); -static void ResetLine(LineElement* elemPtr); - -static ElementClosestProc ClosestLineProc; -static ElementConfigProc ConfigureLineProc; -static ElementDestroyProc DestroyLineProc; -static ElementDrawProc DrawActiveLineProc; -static ElementDrawProc DrawNormalLineProc; -static ElementDrawSymbolProc DrawSymbolProc; -static ElementExtentsProc GetLineExtentsProc; -static ElementToPostScriptProc ActiveLineToPostScriptProc; -static ElementToPostScriptProc NormalLineToPostScriptProc; -static ElementSymbolToPostScriptProc SymbolToPostScriptProc; -static ElementMapProc MapLineProc; -static DistanceProc DistanceToYProc; -static DistanceProc DistanceToXProc; -static DistanceProc DistanceToLineProc; - -static ElementProcs lineProcs = - { - ClosestLineProc, /* Finds the closest element/data - * point */ - ConfigureLineProc, /* Configures the element. */ - DestroyLineProc, /* Destroys the element. */ - DrawActiveLineProc, /* Draws active element */ - DrawNormalLineProc, /* Draws normal element */ - DrawSymbolProc, /* Draws the element symbol. */ - GetLineExtentsProc, /* Find the extents of the element's - * data. */ - ActiveLineToPostScriptProc, /* Prints active element. */ - NormalLineToPostScriptProc, /* Prints normal element. */ - SymbolToPostScriptProc, /* Prints the line's symbol. */ - MapLineProc /* Compute element's screen - * coordinates. */ - }; - -INLINE static int Round(double x) +static int Round(double x) { return (int) (x + ((x < 0.0) ? -0.5 : 0.5)); } @@ -291,61 +228,89 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, 0, 0, NULL, 0} }; -// Create - -Element* Blt_LineElement(Graph* graphPtr) +LineElement::LineElement(Graph* graphPtr, const char* name, Tcl_HashEntry* hPtr) + : Element(graphPtr, name, hPtr) { - LineElement* lePtr = (LineElement*)calloc(1, sizeof(LineElement)); - lePtr->ops = (LineElementOptions*)calloc(1, sizeof(LineElementOptions)); - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - ops->elemPtr = (Element*)lePtr; - - lePtr->procsPtr = &lineProcs; - ops->builtinPenPtr = &lePtr->builtinPen; + Blt_GraphSetObjectClass(&obj, CID_ELEM_LINE); + + smooth_ = PEN_SMOOTH_LINEAR; + fillBgColor_ =NULL; + fillGC_ = NULL; + fillPts_ =NULL; + nFillPts_ = 0; + + symbolPts_.points =NULL; + symbolPts_.length =0; + symbolPts_.map =NULL; + activePts_.points =NULL; + activePts_.length =0; + activePts_.map =NULL; + + xeb_.segments =NULL; + xeb_.length =0; + xeb_.map =NULL; + yeb_.segments =NULL; + yeb_.length =0; + yeb_.map =NULL; + lines_.segments =NULL; + lines_.length =0; + lines_.map =NULL; + + symbolInterval_ =0; + symbolCounter_ =0; + traces_ =NULL; + + ops_ = (LineElementOptions*)calloc(1, sizeof(LineElementOptions)); + LineElementOptions* ops = (LineElementOptions*)ops_; + ops->elemPtr = (Element*)this; + + builtinPenPtr = new LinePen(graphPtr, "builtin", &ops->builtinPen); + ops->builtinPenPtr = builtinPenPtr; - lePtr->builtinPen.init(graphPtr, "builtin", &ops->builtinPen); Tk_InitOptions(graphPtr->interp, (char*)&(ops->builtinPen), - lePtr->builtinPen.optionTable(), graphPtr->tkwin); + builtinPenPtr->optionTable(), graphPtr->tkwin); - lePtr->optionTable = Tk_CreateOptionTable(graphPtr->interp, optionSpecs); + optionTable_ = Tk_CreateOptionTable(graphPtr->interp, optionSpecs); - lePtr->flags = SCALE_SYMBOL; - return (Element*)lePtr; + ops->stylePalette = Blt_Chain_Create(); + // this is an option and will be freed via Tk_FreeConfigOptions + // By default an element's name and label are the same + ops->label = Tcl_Alloc(strlen(name)+1); + if (name) + strcpy((char*)ops->label,(char*)name); + + flags = SCALE_SYMBOL; } -static void DestroyLineProc(Graph* graphPtr, Element* elemPtr) +LineElement::~LineElement() { - LineElement* lePtr = (LineElement*)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops_; if (ops->activePenPtr) Blt_FreePen((Pen *)ops->activePenPtr); if (ops->normalPenPtr) Blt_FreePen((Pen *)ops->normalPenPtr); + if (ops->builtinPenPtr) + delete builtinPenPtr; + + ResetLine(); - ResetLine(lePtr); if (ops->stylePalette) { Blt_FreeStylePalette(ops->stylePalette); Blt_Chain_Destroy(ops->stylePalette); } - if (lePtr->activeIndices) - free(lePtr->activeIndices); - - if (lePtr->fillPts) - free(lePtr->fillPts); - if (lePtr->fillGC) - Tk_FreeGC(graphPtr->display, lePtr->fillGC); + if (fillPts_) + free(fillPts_); + if (fillGC_) + Tk_FreeGC(graphPtr_->display, fillGC_); } -// Configure - -static int ConfigureLineProc(Graph* graphPtr, Element *elemPtr) +int LineElement::configure() { - LineElement* lePtr = (LineElement*)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops_; - if (lePtr->builtinPen.configure() != TCL_OK) + if (builtinPenPtr->configure() != TCL_OK) return TCL_ERROR; // Point to the static normal/active pens if no external pens have been @@ -366,48 +331,700 @@ static int ConfigureLineProc(Graph* graphPtr, Element *elemPtr) gcMask |= GCForeground; gcValues.foreground = ops->fillFgColor->pixel; } - if (lePtr->fillBgColor) { + if (fillBgColor_) { gcMask |= GCBackground; - gcValues.background = lePtr->fillBgColor->pixel; + gcValues.background = fillBgColor_->pixel; } - GC newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues); - if (lePtr->fillGC) - Tk_FreeGC(graphPtr->display, lePtr->fillGC); - lePtr->fillGC = newGC; + GC newGC = Tk_GetGC(graphPtr_->tkwin, gcMask, &gcValues); + if (fillGC_) + Tk_FreeGC(graphPtr_->display, fillGC_); + fillGC_ = newGC; return TCL_OK; } -// Support +void LineElement::map() +{ + LineElementOptions* ops = (LineElementOptions*)ops_; + + ResetLine(); + if (!ops->coords.x || !ops->coords.y || + !ops->coords.x->nValues || !ops->coords.y->nValues) + return; + int np = NUMBEROFPOINTS(ops); + + MapInfo mi; + GetScreenPoints(&mi); + MapSymbols(&mi); + + if ((flags & ACTIVE_PENDING) && (nActiveIndices_ > 0)) + MapActiveSymbols(); + + // Map connecting line segments if they are to be displayed. + smooth_ = ops->reqSmooth; + if ((np > 1) && (ops->builtinPen.traceWidth > 0)) { + // Do smoothing if necessary. This can extend the coordinate array, + // so both mi.points and mi.nPoints may change. + switch (smooth_) { + case PEN_SMOOTH_STEP: + GenerateSteps(&mi); + break; + + case PEN_SMOOTH_NATURAL: + case PEN_SMOOTH_QUADRATIC: + // Can't interpolate with less than three points + if (mi.nScreenPts < 3) + smooth_ = PEN_SMOOTH_LINEAR; + else + GenerateSpline(&mi); + break; + + case PEN_SMOOTH_CATROM: + // Can't interpolate with less than three points + if (mi.nScreenPts < 3) + smooth_ = PEN_SMOOTH_LINEAR; + else + GenerateParametricSpline(&mi); + break; + + default: + break; + } + if (ops->rTolerance > 0.0) + ReducePoints(&mi, ops->rTolerance); + + if (ops->fillBg) + MapFillArea(&mi); + + MapTraces(&mi); + } + free(mi.screenPts); + free(mi.map); + + // Set the symbol size of all the pen styles + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; + link = Blt_Chain_NextLink(link)) { + LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); + LinePen* penPtr = (LinePen *)stylePtr->penPtr; + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + int size = ScaleSymbol(penOps->symbol.size); + stylePtr->symbolSize = size; + stylePtr->errorBarCapWidth = (penOps->errorBarCapWidth > 0) + ? penOps->errorBarCapWidth : Round(size * 0.6666666); + stylePtr->errorBarCapWidth /= 2; + } -static void ResetStylePalette(Blt_Chain styles) + LineStyle **styleMap = (LineStyle**)StyleMap(); + if (((ops->yHigh && ops->yHigh->nValues > 0) && + (ops->yLow && ops->yLow->nValues > 0)) || + ((ops->xHigh && ops->xHigh->nValues > 0) && + (ops->xLow && ops->xLow->nValues > 0)) || + (ops->xError && ops->xError->nValues > 0) || + (ops->yError && ops->yError->nValues > 0)) { + MapErrorBars(styleMap); + } + + MergePens(styleMap); + free(styleMap); +} + +void LineElement::extents(Region2d *extsPtr) { - for (Blt_ChainLink link = Blt_Chain_FirstLink(styles); link; + LineElementOptions* ops = (LineElementOptions*)ops_; + + extsPtr->top = extsPtr->left = DBL_MAX; + extsPtr->bottom = extsPtr->right = -DBL_MAX; + + if (!ops->coords.x || !ops->coords.y || + !ops->coords.x->nValues || !ops->coords.y->nValues) + return; + int np = NUMBEROFPOINTS(ops); + + extsPtr->right = ops->coords.x->max; + if ((ops->coords.x->min <= 0.0) && (ops->axes.x->logScale)) + extsPtr->left = FindElemValuesMinimum(ops->coords.x, DBL_MIN); + else + extsPtr->left = ops->coords.x->min; + + extsPtr->bottom = ops->coords.y->max; + if ((ops->coords.y->min <= 0.0) && (ops->axes.y->logScale)) + extsPtr->top = FindElemValuesMinimum(ops->coords.y, DBL_MIN); + else + extsPtr->top = ops->coords.y->min; + + // Correct the data limits for error bars + if (ops->xError && ops->xError->nValues > 0) { + int i; + + np = MIN(ops->xError->nValues, np); + for (i = 0; i < np; i++) { + double x; + + x = ops->coords.x->values[i] + ops->xError->values[i]; + if (x > extsPtr->right) { + extsPtr->right = x; + } + x = ops->coords.x->values[i] - ops->xError->values[i]; + if (ops->axes.x->logScale) { + // Mirror negative values, instead of ignoring them + if (x < 0.0) + x = -x; + if ((x > DBL_MIN) && (x < extsPtr->left)) + extsPtr->left = x; + } + else if (x < extsPtr->left) + extsPtr->left = x; + } + } + else { + if (ops->xHigh && + (ops->xHigh->nValues > 0) && + (ops->xHigh->max > extsPtr->right)) { + extsPtr->right = ops->xHigh->max; + } + if (ops->xLow && ops->xLow->nValues > 0) { + double left; + + if ((ops->xLow->min <= 0.0) && + (ops->axes.x->logScale)) + left = FindElemValuesMinimum(ops->xLow, DBL_MIN); + else + left = ops->xLow->min; + + if (left < extsPtr->left) + extsPtr->left = left; + } + } + + if (ops->yError && ops->yError->nValues > 0) { + int i; + + np = MIN(ops->yError->nValues, np); + for (i = 0; i < np; i++) { + double y; + + y = ops->coords.y->values[i] + ops->yError->values[i]; + if (y > extsPtr->bottom) { + extsPtr->bottom = y; + } + y = ops->coords.y->values[i] - ops->yError->values[i]; + if (ops->axes.y->logScale) { + if (y < 0.0) { + y = -y; /* Mirror negative values, instead of + * ignoring them. */ + } + if ((y > DBL_MIN) && (y < extsPtr->left)) { + extsPtr->top = y; + } + } else if (y < extsPtr->top) { + extsPtr->top = y; + } + } + } + else { + if (ops->yHigh && + (ops->yHigh->nValues > 0) && + (ops->yHigh->max > extsPtr->bottom)) { + extsPtr->bottom = ops->yHigh->max; + } + if (ops->yLow && ops->yLow->nValues > 0) { + double top; + if ((ops->yLow->min <= 0.0) && + (ops->axes.y->logScale)) + top = FindElemValuesMinimum(ops->yLow, DBL_MIN); + else + top = ops->yLow->min; + + if (top < extsPtr->top) + extsPtr->top = top; + } + } +} + +void LineElement::closest() +{ + LineElementOptions* ops = (LineElementOptions*)ops_; + + ClosestSearch* searchPtr = &graphPtr_->search; + int mode = searchPtr->mode; + if (mode == SEARCH_AUTO) { + LinePen* penPtr = NORMALPEN(ops); + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + mode = SEARCH_POINTS; + if ((NUMBEROFPOINTS(ops) > 1) && (penOps->traceWidth > 0)) + mode = SEARCH_TRACES; + } + if (mode == SEARCH_POINTS) + ClosestPoint(searchPtr); + else { + int found = ClosestTrace(); + if ((!found) && (searchPtr->along != SEARCH_BOTH)) + ClosestPoint(searchPtr); + } +} + +void LineElement::drawActive(Drawable drawable) +{ + LineElementOptions* ops = (LineElementOptions*)ops_; + LinePen* penPtr = (LinePen *)ops->activePenPtr; + + if (!penPtr) + return; + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + + int symbolSize = ScaleSymbol(penOps->symbol.size); + + /* + * nActiveIndices + * > 0 Some points are active. Uses activeArr. + * < 0 All points are active. + * == 0 No points are active. + */ + if (nActiveIndices_ > 0) { + if (flags & ACTIVE_PENDING) + MapActiveSymbols(); + + if (penOps->symbol.type != SYMBOL_NONE) + DrawSymbols(drawable, penPtr, symbolSize, activePts_.length, + activePts_.points); + if (penOps->valueShow != SHOW_NONE) + DrawValues(drawable, penPtr, activePts_.length, activePts_.points, + activePts_.map); + } + else if (nActiveIndices_ < 0) { + if (penOps->traceWidth > 0) { + if (lines_.length > 0) + Blt_Draw2DSegments(graphPtr_->display, drawable, + penPtr->traceGC_, lines_.segments, + lines_.length); + else if (Blt_Chain_GetLength(traces_) > 0) + DrawTraces(drawable, penPtr); + } + if (penOps->symbol.type != SYMBOL_NONE) + DrawSymbols(drawable, penPtr, symbolSize, symbolPts_.length, + symbolPts_.points); + + if (penOps->valueShow != SHOW_NONE) { + DrawValues(drawable, penPtr, symbolPts_.length, symbolPts_.points, + symbolPts_.map); + } + } +} + +void LineElement::drawNormal(Drawable drawable) +{ + LineElementOptions* ops = (LineElementOptions*)ops_; + + // Fill area under the curve + if (fillPts_) { + XPoint *points = (XPoint*)malloc(sizeof(XPoint) * nFillPts_); + + unsigned int count =0; + Point2d *endp, *pp; + for (pp = fillPts_, endp = pp + nFillPts_; + pp < endp; pp++) { + points[count].x = Round(pp->x); + points[count].y = Round(pp->y); + count++; + } + if (ops->fillBg) + Tk_Fill3DPolygon(graphPtr_->tkwin, drawable, ops->fillBg, points, + nFillPts_, 0, TK_RELIEF_FLAT); + free(points); + } + + // Lines: stripchart segments or graph traces + if (lines_.length > 0) { + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); + link; link = Blt_Chain_NextLink(link)) { + + LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); + LinePen* penPtr = (LinePen*)stylePtr->penPtr; + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + if ((stylePtr->lines.length > 0) && + (penOps->errorBarLineWidth > 0)) { + Blt_Draw2DSegments(graphPtr_->display, drawable, penPtr->traceGC_, + stylePtr->lines.segments, stylePtr->lines.length); + } + } + } + else { + LinePen* penPtr = NORMALPEN(ops); + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + + if ((Blt_Chain_GetLength(traces_) > 0) && (penOps->traceWidth > 0)) + DrawTraces(drawable, penPtr); + } + + if (ops->reqMaxSymbols > 0) { + int total = 0; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); + link; link = Blt_Chain_NextLink(link)) { + LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); + total += stylePtr->symbolPts.length; + } + symbolInterval_ = total / ops->reqMaxSymbols; + symbolCounter_ = 0; + } + + // Symbols, error bars, values + + unsigned int count =0; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; link = Blt_Chain_NextLink(link)) { LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); - stylePtr->lines.length = stylePtr->symbolPts.length = 0; - stylePtr->xeb.length = stylePtr->yeb.length = 0; + LinePen* penPtr = (LinePen *)stylePtr->penPtr; + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + + if ((stylePtr->xeb.length > 0) && (penOps->errorBarShow & SHOW_X)) + Blt_Draw2DSegments(graphPtr_->display, drawable, penPtr->errorBarGC_, + stylePtr->xeb.segments, stylePtr->xeb.length); + + if ((stylePtr->yeb.length > 0) && (penOps->errorBarShow & SHOW_Y)) + Blt_Draw2DSegments(graphPtr_->display, drawable, penPtr->errorBarGC_, + stylePtr->yeb.segments, stylePtr->yeb.length); + + if ((stylePtr->symbolPts.length > 0) && + (penOps->symbol.type != SYMBOL_NONE)) + DrawSymbols(drawable, penPtr, stylePtr->symbolSize, + stylePtr->symbolPts.length, stylePtr->symbolPts.points); + + if (penOps->valueShow != SHOW_NONE) + DrawValues(drawable, penPtr, stylePtr->symbolPts.length, + stylePtr->symbolPts.points, symbolPts_.map + count); + + count += stylePtr->symbolPts.length; + } + + symbolInterval_ = 0; +} + +void LineElement::drawSymbol(Drawable drawable, int x, int y, int size) +{ + LineElementOptions* ops = (LineElementOptions*)ops_; + + LinePen* penPtr = NORMALPEN(ops); + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + + if (penOps->traceWidth > 0) { + /* + * Draw an extra line offset by one pixel from the previous to give a + * thicker appearance. This is only for the legend entry. This routine + * is never called for drawing the actual line segments. + */ + XDrawLine(graphPtr_->display, drawable, penPtr->traceGC_, x - size, y, + x + size, y); + XDrawLine(graphPtr_->display, drawable, penPtr->traceGC_, x - size, y + 1, + x + size, y + 1); + } + if (penOps->symbol.type != SYMBOL_NONE) { + Point2d point; + point.x = x; + point.y = y; + DrawSymbols(drawable, penPtr, size, 1, &point); + } +} + +void LineElement::printActive(Blt_Ps ps) +{ + LineElementOptions* ops = (LineElementOptions*)ops_; + + LinePen* penPtr = (LinePen *)ops->activePenPtr; + if (!penPtr) + return; + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + + int symbolSize = ScaleSymbol(penOps->symbol.size); + if (nActiveIndices_ > 0) { + if (flags & ACTIVE_PENDING) + MapActiveSymbols(); + + if (penOps->symbol.type != SYMBOL_NONE) + SymbolsToPostScript(ps, penPtr, symbolSize, activePts_.length, + activePts_.points); + + if (penOps->valueShow != SHOW_NONE) + ValuesToPostScript(ps, penPtr, activePts_.length, activePts_.points, + activePts_.map); + } + else if (nActiveIndices_ < 0) { + if (penOps->traceWidth > 0) { + if (lines_.length > 0) { + SetLineAttributes(ps, penPtr); + Blt_Ps_Draw2DSegments(ps, lines_.segments, lines_.length); + } + if (Blt_Chain_GetLength(traces_) > 0) + TracesToPostScript(ps, (LinePen*)penPtr); + } + if (penOps->symbol.type != SYMBOL_NONE) + SymbolsToPostScript(ps, penPtr, symbolSize, symbolPts_.length, + symbolPts_.points); + if (penOps->valueShow != SHOW_NONE) { + ValuesToPostScript(ps, penPtr, symbolPts_.length, + symbolPts_.points, symbolPts_.map); + } + } +} + +void LineElement::printNormal(Blt_Ps ps) +{ + LineElementOptions* ops = (LineElementOptions*)ops_; + + // Draw fill area + if (fillPts_) { + // Create a path to use for both the polygon and its outline + Blt_Ps_Append(ps, "% start fill area\n"); + Blt_Ps_Polyline(ps, fillPts_, nFillPts_); + + // If the background fill color was specified, draw the polygon in a + // solid fashion with that color + if (fillBgColor_) { + Blt_Ps_XSetBackground(ps, fillBgColor_); + Blt_Ps_Append(ps, "gsave fill grestore\n"); + } + Blt_Ps_XSetForeground(ps, ops->fillFgColor); + if (ops->fillBg) + Blt_Ps_Append(ps, "gsave fill grestore\n"); + else + Blt_Ps_Append(ps, "gsave fill grestore\n"); + + Blt_Ps_Append(ps, "% end fill area\n"); + } + + // Draw lines (strip chart) or traces (xy graph) + if (lines_.length > 0) { + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; + link = Blt_Chain_NextLink(link)) { + LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); + LinePen* penPtr = (LinePen *)stylePtr->penPtr; + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + + if ((stylePtr->lines.length > 0) && (penOps->traceWidth > 0)) { + SetLineAttributes(ps, penPtr); + Blt_Ps_Append(ps, "% start segments\n"); + Blt_Ps_Draw2DSegments(ps, stylePtr->lines.segments, + stylePtr->lines.length); + Blt_Ps_Append(ps, "% end segments\n"); + } + } + } + else { + LinePen* penPtr = NORMALPEN(ops); + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + + if ((Blt_Chain_GetLength(traces_) > 0) && + (penOps->traceWidth > 0)) { + TracesToPostScript(ps, penPtr); + } + } + + // Draw symbols, error bars, values + + unsigned int count =0; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; + link = Blt_Chain_NextLink(link)) { + + LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); + LinePen* penPtr = (LinePen *)stylePtr->penPtr; + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + XColor* colorPtr = penOps->errorBarColor; + if (!colorPtr) + colorPtr = penOps->traceColor; + + if ((stylePtr->xeb.length > 0) && (penOps->errorBarShow & SHOW_X)) { + Blt_Ps_XSetLineAttributes(ps, colorPtr, penOps->errorBarLineWidth, + NULL, CapButt, JoinMiter); + Blt_Ps_Draw2DSegments(ps, stylePtr->xeb.segments, + stylePtr->xeb.length); + } + if ((stylePtr->yeb.length > 0) && (penOps->errorBarShow & SHOW_Y)) { + Blt_Ps_XSetLineAttributes(ps, colorPtr, penOps->errorBarLineWidth, + NULL, CapButt, JoinMiter); + Blt_Ps_Draw2DSegments(ps, stylePtr->yeb.segments, + stylePtr->yeb.length); + } + if ((stylePtr->symbolPts.length > 0) && + (penOps->symbol.type != SYMBOL_NONE)) { + SymbolsToPostScript(ps, penPtr, stylePtr->symbolSize, + stylePtr->symbolPts.length, + stylePtr->symbolPts.points); + } + if (penOps->valueShow != SHOW_NONE) { + ValuesToPostScript(ps, penPtr, stylePtr->symbolPts.length, + stylePtr->symbolPts.points, + symbolPts_.map + count); + } + count += stylePtr->symbolPts.length; + } +} + +void printSymbol(Blt_Ps ps, double x, double y, int size) +{ + LineElementOptions* ops = (LineElementOptions*)ops; + + LinePen* penPtr = NORMALPEN(ops); + LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); + + if (penOps->traceWidth > 0) { + /* + * Draw an extra line offset by one pixel from the previous to give a + * thicker appearance. This is only for the legend entry. This routine + * is never called for drawing the actual line segments. + */ + Blt_Ps_XSetLineAttributes(ps, penOps->traceColor, penOps->traceWidth, + &penOps->traceDashes, CapButt, JoinMiter); + Blt_Ps_Format(ps, "%g %g %d Li\n", x, y, size + size); + } + if (penOps->symbol.type != SYMBOL_NONE) { + Point2d point; + point.x = x; + point.y = y; + SymbolsToPostScript(ps, penPtr, size, 1, &point); + } +} + +// Support + +double LineElement::DistanceToLine(int x, int y, Point2d *p, Point2d *q, + Point2d *t) +{ + double right, left, top, bottom; + + *t = Blt_GetProjection(x, y, p, q); + if (p->x > q->x) + right = p->x, left = q->x; + else + left = p->x, right = q->x; + + if (p->y > q->y) + bottom = p->y, top = q->y; + else + top = p->y, bottom = q->y; + + if (t->x > right) + t->x = right; + else if (t->x < left) + t->x = left; + + if (t->y > bottom) + t->y = bottom; + else if (t->y < top) + t->y = top; + + return hypot((t->x - x), (t->y - y)); +} + +double LineElement::DistanceToX(int x, int y, Point2d *p, Point2d *q, + Point2d *t) +{ + double dx, dy; + double d; + + if (p->x > q->x) { + if ((x > p->x) || (x < q->x)) { + return DBL_MAX; /* X-coordinate outside line segment. */ + } + } else { + if ((x > q->x) || (x < p->x)) { + return DBL_MAX; /* X-coordinate outside line segment. */ + } + } + dx = p->x - q->x; + dy = p->y - q->y; + t->x = (double)x; + if (fabs(dx) < DBL_EPSILON) { + double d1, d2; + /* + * Same X-coordinate indicates a vertical line. Pick the closest end + * point. + */ + d1 = p->y - y; + d2 = q->y - y; + if (fabs(d1) < fabs(d2)) { + t->y = p->y, d = d1; + } else { + t->y = q->y, d = d2; + } } + else if (fabs(dy) < DBL_EPSILON) { + /* Horizontal line. */ + t->y = p->y, d = p->y - y; + } + else { + double m = dy / dx; + double b = p->y - (m * p->x); + t->y = (x * m) + b; + d = y - t->y; + } + + return fabs(d); } -static int ScaleSymbol(LineElement* lePtr, int normalSize) +double LineElement::DistanceToY(int x, int y, Point2d *p, Point2d *q, + Point2d *t) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + double dx, dy; + double d; + + if (p->y > q->y) { + if ((y > p->y) || (y < q->y)) { + return DBL_MAX; + } + } + else { + if ((y > q->y) || (y < p->y)) { + return DBL_MAX; + } + } + dx = p->x - q->x; + dy = p->y - q->y; + t->y = y; + if (fabs(dy) < DBL_EPSILON) { + double d1, d2; + + /* Save Y-coordinate indicates an horizontal line. Pick the closest end + * point. */ + d1 = p->x - x; + d2 = q->x - x; + if (fabs(d1) < fabs(d2)) { + t->x = p->x, d = d1; + } + else { + t->x = q->x, d = d2; + } + } + else if (fabs(dx) < DBL_EPSILON) { + /* Vertical line. */ + t->x = p->x, d = p->x - x; + } + else { + double m = dy / dx; + double b = p->y - (m * p->x); + t->x = (y - b) / m; + d = x - t->x; + } + + return fabs(d); +} + +int LineElement::ScaleSymbol(int normalSize) +{ + LineElementOptions* ops = (LineElementOptions*)ops; double scale = 1.0; if (ops->scaleSymbols) { double xRange = (ops->axes.x->max - ops->axes.x->min); double yRange = (ops->axes.y->max - ops->axes.y->min); // Save the ranges as a baseline for future scaling - if (lePtr->flags & SCALE_SYMBOL) { - lePtr->xRange = xRange; - lePtr->yRange = yRange; - lePtr->flags &= ~SCALE_SYMBOL; + if (flags & SCALE_SYMBOL) { + xRange_ = xRange; + yRange_ = yRange; + flags &= ~SCALE_SYMBOL; } else { // Scale the symbol by the smallest change in the X or Y axes - double xScale = lePtr->xRange / xRange; - double yScale = lePtr->yRange / yRange; + double xScale = xRange / xRange; + double yScale = yRange / yRange; scale = MIN(xScale, yScale); } } @@ -415,8 +1032,7 @@ static int ScaleSymbol(LineElement* lePtr, int normalSize) // Don't let the size of symbols go unbounded. Both X and Win32 drawing // routines assume coordinates to be a signed short int. - int maxSize = (int)MIN(lePtr->obj.graphPtr->hRange, - lePtr->obj.graphPtr->vRange); + int maxSize = (int)MIN(obj.graphPtr->hRange, obj.graphPtr->vRange); if (newSize > maxSize) newSize = maxSize; @@ -426,10 +1042,9 @@ static int ScaleSymbol(LineElement* lePtr, int normalSize) return newSize; } -static void GetScreenPoints(Graph* graphPtr, LineElement* lePtr, - MapInfo *mapPtr) +void LineElement::GetScreenPoints(MapInfo *mapPtr) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; if (!ops->coords.x || !ops->coords.y) { mapPtr->screenPts = NULL; @@ -444,7 +1059,7 @@ static void GetScreenPoints(Graph* graphPtr, LineElement* lePtr, int* map = (int*)malloc(sizeof(int) * np); int count = 0; - if (graphPtr->inverted) { + if (graphPtr_->inverted) { for (int i = 0; i < np; i++) { if ((isfinite(x[i])) && (isfinite(y[i]))) { points[count].x = Blt_HMap(ops->axes.y, y[i]); @@ -469,19 +1084,17 @@ static void GetScreenPoints(Graph* graphPtr, LineElement* lePtr, mapPtr->map = map; } -static void ReducePoints(MapInfo *mapPtr, double tolerance) +void LineElement::ReducePoints(MapInfo *mapPtr, double tolerance) { int* simple = (int*)malloc(mapPtr->nScreenPts * sizeof(int)); int* map = (int*)malloc(mapPtr->nScreenPts * sizeof(int)); Point2d *screenPts = (Point2d*)malloc(mapPtr->nScreenPts * sizeof(Point2d)); int np = Blt_SimplifyLine(mapPtr->screenPts, 0, mapPtr->nScreenPts - 1, tolerance, simple); - for (int i = 0; i < np; i++) { - int k; - - k = simple[i]; - screenPts[i] = mapPtr->screenPts[k]; - map[i] = mapPtr->map[k]; + for (int ii=0; ii<np; ii++) { + int kk = simple[ii]; + screenPts[ii] = mapPtr->screenPts[kk]; + map[ii] = mapPtr->map[kk]; } free(mapPtr->screenPts); free(mapPtr->map); @@ -491,7 +1104,7 @@ static void ReducePoints(MapInfo *mapPtr, double tolerance) mapPtr->nScreenPts = np; } -static void GenerateSteps(MapInfo *mapPtr) +void LineElement::GenerateSteps(MapInfo *mapPtr) { int newSize = ((mapPtr->nScreenPts - 1) * 2) + 1; Point2d *screenPts = (Point2d*)malloc(newSize * sizeof(Point2d)); @@ -518,8 +1131,7 @@ static void GenerateSteps(MapInfo *mapPtr) mapPtr->nScreenPts = newSize; } -static void GenerateSpline(Graph* graphPtr, LineElement* lePtr, - MapInfo *mapPtr) +void LineElement::GenerateSpline(MapInfo *mapPtr) { Point2d *origPts, *iPts; int *map; @@ -536,8 +1148,8 @@ static void GenerateSpline(Graph* graphPtr, LineElement* lePtr, * increasing */ } } - if (((origPts[0].x > (double)graphPtr->right)) || - ((origPts[mapPtr->nScreenPts - 1].x < (double)graphPtr->left))) { + if (((origPts[0].x > (double)graphPtr_->right)) || + ((origPts[mapPtr->nScreenPts - 1].x < (double)graphPtr_->left))) { return; /* All points are clipped */ } @@ -546,7 +1158,7 @@ static void GenerateSpline(Graph* graphPtr, LineElement* lePtr, * that we can select the abscissas of the interpolated points from each * pixel horizontally across the plotting area. */ - extra = (graphPtr->right - graphPtr->left) + 1; + extra = (graphPtr_->right - graphPtr_->left) + 1; if (extra < 1) { return; } @@ -567,8 +1179,8 @@ static void GenerateSpline(Graph* graphPtr, LineElement* lePtr, count++; /* Is any part of the interval (line segment) in the plotting area? */ - if ((origPts[j].x >= (double)graphPtr->left) || - (origPts[i].x <= (double)graphPtr->right)) { + if ((origPts[j].x >= (double)graphPtr_->left) || + (origPts[i].x <= (double)graphPtr_->right)) { double x, last; x = origPts[i].x + 1.0; @@ -584,8 +1196,8 @@ static void GenerateSpline(Graph* graphPtr, LineElement* lePtr, * Pick the max of the starting X-coordinate and the left edge and * the min of the last X-coordinate and the right edge. */ - x = MAX(x, (double)graphPtr->left); - last = MIN(origPts[j].x, (double)graphPtr->right); + x = MAX(x, (double)graphPtr_->left); + last = MIN(origPts[j].x, (double)graphPtr_->right); /* Add the extra x-coordinates to the interval. */ while (x < last) { @@ -597,18 +1209,19 @@ static void GenerateSpline(Graph* graphPtr, LineElement* lePtr, } niPts = count; result = 0; - if (lePtr->smooth == PEN_SMOOTH_NATURAL) { + if (smooth_ == PEN_SMOOTH_NATURAL) result = Blt_NaturalSpline(origPts, nOrigPts, iPts, niPts); - } else if (lePtr->smooth == PEN_SMOOTH_QUADRATIC) { + else if (smooth_ == PEN_SMOOTH_QUADRATIC) result = Blt_QuadraticSpline(origPts, nOrigPts, iPts, niPts); - } + if (!result) { /* The spline interpolation failed. We'll fallback to the current * coordinates and do no smoothing (standard line segments). */ - lePtr->smooth = PEN_SMOOTH_LINEAR; + smooth_ = PEN_SMOOTH_LINEAR; free(iPts); free(map); - } else { + } + else { free(mapPtr->screenPts); free(mapPtr->map); mapPtr->map = map; @@ -617,8 +1230,7 @@ static void GenerateSpline(Graph* graphPtr, LineElement* lePtr, } } -static void GenerateParametricSpline(Graph* graphPtr, LineElement* lePtr, - MapInfo *mapPtr) +void LineElement::GenerateParametricSpline(MapInfo *mapPtr) { Region2d exts; Point2d *origPts, *iPts; @@ -629,7 +1241,7 @@ static void GenerateParametricSpline(Graph* graphPtr, LineElement* lePtr, nOrigPts = mapPtr->nScreenPts; origPts = mapPtr->screenPts; - Blt_GraphExtents(graphPtr, &exts); + Blt_GraphExtents(graphPtr_, &exts); /* * Populate the x2 array with both the original X-coordinates and extra @@ -704,19 +1316,20 @@ static void GenerateParametricSpline(Graph* graphPtr, LineElement* lePtr, count++; niPts = count; result = 0; - if (lePtr->smooth == PEN_SMOOTH_NATURAL) { + if (smooth_ == PEN_SMOOTH_NATURAL) result = Blt_NaturalParametricSpline(origPts, nOrigPts, &exts, 0, iPts, niPts); - } else if (lePtr->smooth == PEN_SMOOTH_CATROM) { + else if (smooth_ == PEN_SMOOTH_CATROM) result = Blt_CatromParametricSpline(origPts, nOrigPts, iPts, niPts); - } + if (!result) { /* The spline interpolation failed. We will fall back to the current * coordinates and do no smoothing (standard line segments). */ - lePtr->smooth = PEN_SMOOTH_LINEAR; + smooth_ = PEN_SMOOTH_LINEAR; free(iPts); free(map); - } else { + } + else { free(mapPtr->screenPts); free(mapPtr->map); mapPtr->map = map; @@ -725,7 +1338,7 @@ static void GenerateParametricSpline(Graph* graphPtr, LineElement* lePtr, } } -static void MapSymbols(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) +void LineElement::MapSymbols(MapInfo *mapPtr) { Region2d exts; Point2d *pp; @@ -734,7 +1347,7 @@ static void MapSymbols(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) Point2d* points = (Point2d*)malloc(sizeof(Point2d) * mapPtr->nScreenPts); int *map = (int*)malloc(sizeof(int) * mapPtr->nScreenPts); - Blt_GraphExtents(graphPtr, &exts); + Blt_GraphExtents(graphPtr_, &exts); int count = 0; for (pp = mapPtr->screenPts, i = 0; i < mapPtr->nScreenPts; i++, pp++) { @@ -745,40 +1358,40 @@ static void MapSymbols(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) count++; } } - lePtr->symbolPts.points = points; - lePtr->symbolPts.length = count; - lePtr->symbolPts.map = map; + symbolPts_.points = points; + symbolPts_.length = count; + symbolPts_.map = map; } -static void MapActiveSymbols(Graph* graphPtr, LineElement* lePtr) +void LineElement::MapActiveSymbols() { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; - if (lePtr->activePts.points) { - free(lePtr->activePts.points); - lePtr->activePts.points = NULL; + if (activePts_.points) { + free(activePts_.points); + activePts_.points = NULL; } - if (lePtr->activePts.map) { - free(lePtr->activePts.map); - lePtr->activePts.map = NULL; + if (activePts_.map) { + free(activePts_.map); + activePts_.map = NULL; } Region2d exts; - Blt_GraphExtents(graphPtr, &exts); + Blt_GraphExtents(graphPtr_, &exts); - Point2d *points = (Point2d*)malloc(sizeof(Point2d) * lePtr->nActiveIndices); - int* map = (int*)malloc(sizeof(int) * lePtr->nActiveIndices); + Point2d *points = (Point2d*)malloc(sizeof(Point2d) * nActiveIndices_); + int* map = (int*)malloc(sizeof(int) * nActiveIndices_); int np = NUMBEROFPOINTS(ops); int count = 0; if (ops->coords.x && ops->coords.y) { - for (int ii=0; ii<lePtr->nActiveIndices; ii++) { - int iPoint = lePtr->activeIndices[ii]; + for (int ii=0; ii<nActiveIndices_; ii++) { + int iPoint = activeIndices_[ii]; if (iPoint >= np) continue; double x = ops->coords.x->values[iPoint]; double y = ops->coords.y->values[iPoint]; - points[count] = Blt_Map2D(graphPtr, x, y, &ops->axes); + points[count] = Blt_Map2D(graphPtr_, x, y, &ops->axes); map[count] = iPoint; if (PointInRegion(&exts, points[count].x, points[count].y)) { count++; @@ -787,152 +1400,131 @@ static void MapActiveSymbols(Graph* graphPtr, LineElement* lePtr) } if (count > 0) { - lePtr->activePts.points = points; - lePtr->activePts.map = map; + activePts_.points = points; + activePts_.map = map; } else { free(points); free(map); } - lePtr->activePts.length = count; - lePtr->flags &= ~ACTIVE_PENDING; + activePts_.length = count; + flags &= ~ACTIVE_PENDING; } -static void MergePens(LineElement* lePtr, LineStyle **styleMap) +void LineElement::MergePens(LineStyle **styleMap) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; if (Blt_Chain_GetLength(ops->stylePalette) < 2) { Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); - stylePtr->lines.length = lePtr->lines.length; - stylePtr->lines.segments = lePtr->lines.segments; - stylePtr->symbolPts.length = lePtr->symbolPts.length; - stylePtr->symbolPts.points = lePtr->symbolPts.points; - stylePtr->xeb.length = lePtr->xeb.length; - stylePtr->xeb.segments = lePtr->xeb.segments; - stylePtr->yeb.length = lePtr->yeb.length; - stylePtr->yeb.segments = lePtr->yeb.segments; + stylePtr->lines.length = lines_.length; + stylePtr->lines.segments = lines_.segments; + stylePtr->symbolPts.length = symbolPts_.length; + stylePtr->symbolPts.points = symbolPts_.points; + stylePtr->xeb.length = xeb_.length; + stylePtr->xeb.segments = xeb_.segments; + stylePtr->yeb.length = yeb_.length; + stylePtr->yeb.segments = yeb_.segments; return; } /* We have more than one style. Group line segments and points of like pen * styles. */ - if (lePtr->lines.length > 0) { - Blt_ChainLink link; - Segment2d *sp; - int *ip; - - Segment2d* segments = - (Segment2d*)malloc(lePtr->lines.length * sizeof(Segment2d)); - int* map = (int*)malloc(lePtr->lines.length * sizeof(int)); - sp = segments, ip = map; - for (link = Blt_Chain_FirstLink(ops->stylePalette); + if (lines_.length > 0) { + Segment2d* segments = (Segment2d*)malloc(lines_.length * sizeof(Segment2d)); + int* map = (int*)malloc(lines_.length * sizeof(int)); + Segment2d *sp = segments; + int* ip = map; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; link = Blt_Chain_NextLink(link)) { LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); stylePtr->lines.segments = sp; - for (int i = 0; i < lePtr->lines.length; i++) { - int iData; - - iData = lePtr->lines.map[i]; + for (int ii=0; ii<lines_.length; ii++) { + int iData = lines_.map[ii]; if (styleMap[iData] == stylePtr) { - *sp++ = lePtr->lines.segments[i]; + *sp++ = lines_.segments[ii]; *ip++ = iData; } } stylePtr->lines.length = sp - stylePtr->lines.segments; } - free(lePtr->lines.segments); - lePtr->lines.segments = segments; - free(lePtr->lines.map); - lePtr->lines.map = map; - } - if (lePtr->symbolPts.length > 0) { - Blt_ChainLink link; - int *ip; - Point2d *pp; - - Point2d* points = - (Point2d*)malloc(lePtr->symbolPts.length * sizeof(Point2d)); - int* map = (int*)malloc(lePtr->symbolPts.length * sizeof(int)); - pp = points, ip = map; - for (link = Blt_Chain_FirstLink(ops->stylePalette); + free(lines_.segments); + lines_.segments = segments; + free(lines_.map); + lines_.map = map; + } + + if (symbolPts_.length > 0) { + Point2d* points = (Point2d*)malloc(symbolPts_.length * sizeof(Point2d)); + int* map = (int*)malloc(symbolPts_.length * sizeof(int)); + Point2d *pp = points; + int* ip = map; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; link = Blt_Chain_NextLink(link)) { LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); stylePtr->symbolPts.points = pp; - for (int i = 0; i < lePtr->symbolPts.length; i++) { - int iData; - - iData = lePtr->symbolPts.map[i]; + for (int ii=0; ii<symbolPts_.length; ii++) { + int iData = symbolPts_.map[ii]; if (styleMap[iData] == stylePtr) { - *pp++ = lePtr->symbolPts.points[i]; + *pp++ = symbolPts_.points[ii]; *ip++ = iData; } } stylePtr->symbolPts.length = pp - stylePtr->symbolPts.points; } - free(lePtr->symbolPts.points); - free(lePtr->symbolPts.map); - lePtr->symbolPts.points = points; - lePtr->symbolPts.map = map; - } - if (lePtr->xeb.length > 0) { - Segment2d *sp; - int *ip; - Blt_ChainLink link; - - Segment2d *segments = - (Segment2d*)malloc(lePtr->xeb.length * sizeof(Segment2d)); - int* map = (int*)malloc(lePtr->xeb.length * sizeof(int)); - sp = segments, ip = map; - for (link = Blt_Chain_FirstLink(ops->stylePalette); + free(symbolPts_.points); + free(symbolPts_.map); + symbolPts_.points = points; + symbolPts_.map = map; + } + + if (xeb_.length > 0) { + Segment2d *segments = (Segment2d*)malloc(xeb_.length * sizeof(Segment2d)); + int* map = (int*)malloc(xeb_.length * sizeof(int)); + Segment2d *sp = segments; + int* ip = map; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; link = Blt_Chain_NextLink(link)) { LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); stylePtr->xeb.segments = sp; - for (int i = 0; i < lePtr->xeb.length; i++) { - int iData; - - iData = lePtr->xeb.map[i]; + for (int ii=0; ii<xeb_.length; ii++) { + int iData = xeb_.map[ii]; if (styleMap[iData] == stylePtr) { - *sp++ = lePtr->xeb.segments[i]; + *sp++ = xeb_.segments[ii]; *ip++ = iData; } } stylePtr->xeb.length = sp - stylePtr->xeb.segments; } - free(lePtr->xeb.segments); - free(lePtr->xeb.map); - lePtr->xeb.segments = segments; - lePtr->xeb.map = map; - } - if (lePtr->yeb.length > 0) { - Segment2d *sp; - int *ip; - Blt_ChainLink link; - - Segment2d *segments = - (Segment2d*)malloc(lePtr->yeb.length * sizeof(Segment2d)); - int* map = (int*)malloc(lePtr->yeb.length * sizeof(int)); - sp = segments, ip = map; - for (link = Blt_Chain_FirstLink(ops->stylePalette); + free(xeb_.segments); + free(xeb_.map); + xeb_.segments = segments; + xeb_.map = map; + } + + if (yeb_.length > 0) { + Segment2d *segments = (Segment2d*)malloc(yeb_.length * sizeof(Segment2d)); + int* map = (int*)malloc(yeb_.length * sizeof(int)); + Segment2d *sp = segments; + int* ip = map; + for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; link = Blt_Chain_NextLink(link)) { LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); stylePtr->yeb.segments = sp; - for (int i = 0; i < lePtr->yeb.length; i++) { - int iData; - - iData = lePtr->yeb.map[i]; + for (int ii=0; ii<yeb_.length; ii++) { + int iData = yeb_.map[ii]; if (styleMap[iData] == stylePtr) { - *sp++ = lePtr->yeb.segments[i]; + *sp++ = yeb_.segments[ii]; *ip++ = iData; } } stylePtr->yeb.length = sp - stylePtr->yeb.segments; } - free(lePtr->yeb.segments); - lePtr->yeb.segments = segments; - free(lePtr->yeb.map); - lePtr->yeb.map = map; + free(yeb_.segments); + yeb_.segments = segments; + free(yeb_.map); + yeb_.map = map; } } @@ -941,31 +1533,27 @@ static void MergePens(LineElement* lePtr, LineStyle **styleMap) #define CLIP_RIGHT (1<<2) #define CLIP_LEFT (1<<3) -INLINE static int OutCode(Region2d *extsPtr, Point2d *p) +int LineElement::OutCode(Region2d *extsPtr, Point2d *p) { - int code; - - code = 0; - if (p->x > extsPtr->right) { + int code =0; + if (p->x > extsPtr->right) code |= CLIP_RIGHT; - } else if (p->x < extsPtr->left) { + else if (p->x < extsPtr->left) code |= CLIP_LEFT; - } - if (p->y > extsPtr->bottom) { + + if (p->y > extsPtr->bottom) code |= CLIP_BOTTOM; - } else if (p->y < extsPtr->top) { + else if (p->y < extsPtr->top) code |= CLIP_TOP; - } + return code; } -static int ClipSegment(Region2d *extsPtr, int code1, int code2, - Point2d *p, Point2d *q) +int LineElement::ClipSegment(Region2d *extsPtr, int code1, int code2, + Point2d *p, Point2d *q) { - int inside, outside; - - inside = ((code1 | code2) == 0); - outside = ((code1 & code2) != 0); + int inside = ((code1 | code2) == 0); + int outside = ((code1 & code2) != 0); /* * In the worst case, we'll clip the line segment against each of the four @@ -1005,61 +1593,56 @@ static int ClipSegment(Region2d *extsPtr, int code1, int code2, return (!inside); } -static void SaveTrace(LineElement* lePtr, int start, int length, - MapInfo *mapPtr) +void LineElement::SaveTrace(int start, int length, MapInfo *mapPtr) { - int i, j; - bltTrace *tracePtr = (bltTrace*)malloc(sizeof(bltTrace)); Point2d *screenPts = (Point2d*)malloc(sizeof(Point2d) * length); int* map = (int*)malloc(sizeof(int) * length); - /* Copy the screen coordinates of the trace into the point array */ + // Copy the screen coordinates of the trace into the point array if (mapPtr->map) { - for (i = 0, j = start; i < length; i++, j++) { - screenPts[i].x = mapPtr->screenPts[j].x; - screenPts[i].y = mapPtr->screenPts[j].y; - map[i] = mapPtr->map[j]; + for (int ii=0, jj=start; ii<length; ii++, jj++) { + screenPts[ii].x = mapPtr->screenPts[jj].x; + screenPts[ii].y = mapPtr->screenPts[jj].y; + map[ii] = mapPtr->map[jj]; } } else { - for (i = 0, j = start; i < length; i++, j++) { - screenPts[i].x = mapPtr->screenPts[j].x; - screenPts[i].y = mapPtr->screenPts[j].y; - map[i] = j; + for (int ii=0, jj=start; ii<length; ii++, jj++) { + screenPts[ii].x = mapPtr->screenPts[jj].x; + screenPts[ii].y = mapPtr->screenPts[jj].y; + map[ii] = jj; } } tracePtr->screenPts.length = length; tracePtr->screenPts.points = screenPts; tracePtr->screenPts.map = map; tracePtr->start = start; - if (lePtr->traces == NULL) { - lePtr->traces = Blt_Chain_Create(); - } - Blt_Chain_Append(lePtr->traces, tracePtr); + if (traces_ == NULL) + traces_ = Blt_Chain_Create(); + + Blt_Chain_Append(traces_, tracePtr); } -static void FreeTraces(LineElement* lePtr) +void LineElement::FreeTraces() { - Blt_ChainLink link; - - for (link = Blt_Chain_FirstLink(lePtr->traces); link; + for (Blt_ChainLink link = Blt_Chain_FirstLink(traces_); link; link = Blt_Chain_NextLink(link)) { bltTrace *tracePtr = (bltTrace*)Blt_Chain_GetValue(link); free(tracePtr->screenPts.map); free(tracePtr->screenPts.points); free(tracePtr); } - Blt_Chain_Destroy(lePtr->traces); - lePtr->traces = NULL; + Blt_Chain_Destroy(traces_); + traces_ = NULL; } -static void MapTraces(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) +void LineElement::MapTraces(MapInfo *mapPtr) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; Region2d exts; - Blt_GraphExtents(graphPtr, &exts); + Blt_GraphExtents(graphPtr_, &exts); int count = 1; int code1 = OutCode(&exts, mapPtr->screenPts); Point2d* p = mapPtr->screenPts; @@ -1089,7 +1672,7 @@ static void MapTraces(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) if (count > 1) { start = ii - count; - SaveTrace(lePtr, start, count, mapPtr); + SaveTrace(start, count, mapPtr); count = 1; } } @@ -1104,7 +1687,7 @@ static void MapTraces(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) */ start = ii - (count - 1); - SaveTrace(lePtr, start, count, mapPtr); + SaveTrace(start, count, mapPtr); mapPtr->screenPts[ii] = s; count = 1; } @@ -1113,28 +1696,28 @@ static void MapTraces(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) } if (count > 1) { start = ii - count; - SaveTrace(lePtr, start, count, mapPtr); + SaveTrace(start, count, mapPtr); } } -static void MapFillArea(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) +void LineElement::MapFillArea(MapInfo *mapPtr) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; - if (lePtr->fillPts) { - free(lePtr->fillPts); - lePtr->fillPts = NULL; - lePtr->nFillPts = 0; + if (fillPts_) { + free(fillPts_); + fillPts_ = NULL; + nFillPts_ = 0; } if (mapPtr->nScreenPts < 3) return; int np = mapPtr->nScreenPts + 3; Region2d exts; - Blt_GraphExtents(graphPtr, &exts); + Blt_GraphExtents(graphPtr_, &exts); Point2d* origPts = (Point2d*)malloc(sizeof(Point2d) * np); - if (graphPtr->inverted) { + if (graphPtr_->inverted) { double minX; int i; @@ -1155,11 +1738,11 @@ static void MapFillArea(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) origPts[i].y = origPts[0].y; i++; origPts[i] = origPts[0]; - } else { - double maxY; + } + else { int i; - maxY = (double)ops->axes.y->bottom; + double maxY = (double)ops->axes.y->bottom; for (i = 0; i < mapPtr->nScreenPts; i++) { origPts[i].x = mapPtr->screenPts[i].x + 1; origPts[i].y = mapPtr->screenPts[i].y; @@ -1182,74 +1765,80 @@ static void MapFillArea(Graph* graphPtr, LineElement* lePtr, MapInfo *mapPtr) np = Blt_PolyRectClip(&exts, origPts, np - 1, clipPts); free(origPts); - if (np < 3) { + if (np < 3) free(clipPts); - } else { - lePtr->fillPts = clipPts; - lePtr->nFillPts = np; + else { + fillPts_ = clipPts; + nFillPts_ = np; } } -static void ResetLine(LineElement* lePtr) +void LineElement::ResetLine() { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - FreeTraces(lePtr); - ResetStylePalette(ops->stylePalette); - if (lePtr->symbolPts.points) { - free(lePtr->symbolPts.points); - lePtr->symbolPts.points = NULL; - } - - if (lePtr->symbolPts.map) - free(lePtr->symbolPts.map); - lePtr->symbolPts.map = NULL; - lePtr->symbolPts.length = 0; - - if (lePtr->lines.segments) - free(lePtr->lines.segments); - lePtr->lines.segments = NULL; - lePtr->lines.length = 0; - - if (lePtr->lines.map) - free(lePtr->lines.map); - lePtr->lines.map = NULL; - - if (lePtr->activePts.points) - free(lePtr->activePts.points); - lePtr->activePts.points = NULL; - lePtr->activePts.length = 0; - - if (lePtr->activePts.map) - free(lePtr->activePts.map); - lePtr->activePts.map = NULL; - - if (lePtr->xeb.segments) - free(lePtr->xeb.segments); - lePtr->xeb.segments = NULL; - - if (lePtr->xeb.map) - free(lePtr->xeb.map); - lePtr->xeb.map = NULL; - lePtr->xeb.length = 0; - - if (lePtr->yeb.segments) - free(lePtr->yeb.segments); - lePtr->yeb.segments = NULL; - lePtr->yeb.length = 0; - - if (lePtr->yeb.map) - free(lePtr->yeb.map); - lePtr->yeb.map = NULL; + LineElementOptions* ops = (LineElementOptions*)ops_; + + FreeTraces(); + + for (Blt_ChainLink link = Blt_Chain_FirstLink(styles); link; + link = Blt_Chain_NextLink(link)) { + LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); + stylePtr->lines.length = stylePtr->symbolPts.length = 0; + stylePtr->xeb.length = stylePtr->yeb.length = 0; + } + + if (symbolPts_.points) { + free(symbolPts_.points); + symbolPts_.points = NULL; + } + + if (symbolPts_.map) + free(symbolPts_.map); + symbolPts_.map = NULL; + symbolPts_.length = 0; + + if (lines_.segments) + free(lines_.segments); + lines_.segments = NULL; + lines_.length = 0; + + if (lines_.map) + free(lines_.map); + lines_.map = NULL; + + if (activePts_.points) + free(activePts_.points); + activePts_.points = NULL; + activePts_.length = 0; + + if (activePts_.map) + free(activePts_.map); + activePts_.map = NULL; + + if (xeb_.segments) + free(xeb_.segments); + xeb_.segments = NULL; + + if (xeb_.map) + free(xeb_.map); + xeb_.map = NULL; + xeb_.length = 0; + + if (yeb_.segments) + free(yeb_.segments); + yeb_.segments = NULL; + yeb_.length = 0; + + if (yeb_.map) + free(yeb_.map); + yeb_.map = NULL; } -static void MapErrorBars(Graph* graphPtr, LineElement* lePtr, - LineStyle **styleMap) +void LineElement::MapErrorBars(LineStyle **styleMap) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; Region2d exts; - Blt_GraphExtents(graphPtr, &exts); + Blt_GraphExtents(graphPtr_, &exts); int n =0; int np = NUMBEROFPOINTS(ops); @@ -1289,8 +1878,8 @@ static void MapErrorBars(Graph* graphPtr, LineElement* lePtr, if ((isfinite(high)) && (isfinite(low))) { Point2d p, q; - p = Blt_Map2D(graphPtr, high, y, &ops->axes); - q = Blt_Map2D(graphPtr, low, y, &ops->axes); + p = Blt_Map2D(graphPtr_, high, y, &ops->axes); + q = Blt_Map2D(graphPtr_, low, y, &ops->axes); segPtr->p = p; segPtr->q = q; if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) { @@ -1316,9 +1905,9 @@ static void MapErrorBars(Graph* graphPtr, LineElement* lePtr, } } } - lePtr->xeb.segments = errorBars; - lePtr->xeb.length = segPtr - errorBars; - lePtr->xeb.map = errorToData; + xeb_.segments = errorBars; + xeb_.length = segPtr - errorBars; + xeb_.map = errorToData; } n =0; @@ -1358,8 +1947,8 @@ static void MapErrorBars(Graph* graphPtr, LineElement* lePtr, if ((isfinite(high)) && (isfinite(low))) { Point2d p, q; - p = Blt_Map2D(graphPtr, x, high, &ops->axes); - q = Blt_Map2D(graphPtr, x, low, &ops->axes); + p = Blt_Map2D(graphPtr_, x, high, &ops->axes); + q = Blt_Map2D(graphPtr_, x, low, &ops->axes); segPtr->p = p; segPtr->q = q; if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) { @@ -1385,220 +1974,16 @@ static void MapErrorBars(Graph* graphPtr, LineElement* lePtr, } } } - lePtr->yeb.segments = errorBars; - lePtr->yeb.length = segPtr - errorBars; - lePtr->yeb.map = errorToData; - } -} - -static void MapLineProc(Graph* graphPtr, Element *elemPtr) -{ - LineElement* lePtr = (LineElement *)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - ResetLine(lePtr); - if (!ops->coords.x || !ops->coords.y || - !ops->coords.x->nValues || !ops->coords.y->nValues) - return; - int np = NUMBEROFPOINTS(ops); - - MapInfo mi; - GetScreenPoints(graphPtr, lePtr, &mi); - MapSymbols(graphPtr, lePtr, &mi); - - if ((lePtr->flags & ACTIVE_PENDING) && (lePtr->nActiveIndices > 0)) - MapActiveSymbols(graphPtr, lePtr); - - // Map connecting line segments if they are to be displayed. - lePtr->smooth = ops->reqSmooth; - if ((np > 1) && (ops->builtinPen.traceWidth > 0)) { - // Do smoothing if necessary. This can extend the coordinate array, - // so both mi.points and mi.nPoints may change. - switch (lePtr->smooth) { - case PEN_SMOOTH_STEP: - GenerateSteps(&mi); - break; - - case PEN_SMOOTH_NATURAL: - case PEN_SMOOTH_QUADRATIC: - // Can't interpolate with less than three points - if (mi.nScreenPts < 3) - lePtr->smooth = PEN_SMOOTH_LINEAR; - else - GenerateSpline(graphPtr, lePtr, &mi); - break; - - case PEN_SMOOTH_CATROM: - // Can't interpolate with less than three points - if (mi.nScreenPts < 3) - lePtr->smooth = PEN_SMOOTH_LINEAR; - else - GenerateParametricSpline(graphPtr, lePtr, &mi); - break; - - default: - break; - } - if (ops->rTolerance > 0.0) { - ReducePoints(&mi, ops->rTolerance); - } - if (ops->fillBg) { - MapFillArea(graphPtr, lePtr, &mi); - } - MapTraces(graphPtr, lePtr, &mi); - } - free(mi.screenPts); - free(mi.map); - - // Set the symbol size of all the pen styles - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; - link = Blt_Chain_NextLink(link)) { - LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); - LinePen* penPtr = (LinePen *)stylePtr->penPtr; - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - int size = ScaleSymbol(lePtr, penOps->symbol.size); - stylePtr->symbolSize = size; - stylePtr->errorBarCapWidth = (penOps->errorBarCapWidth > 0) - ? penOps->errorBarCapWidth : Round(size * 0.6666666); - stylePtr->errorBarCapWidth /= 2; - } - - LineStyle **styleMap = (LineStyle **)Blt_StyleMap((Element *)lePtr); - if (((ops->yHigh && ops->yHigh->nValues > 0) && - (ops->yLow && ops->yLow->nValues > 0)) || - ((ops->xHigh && ops->xHigh->nValues > 0) && - (ops->xLow && ops->xLow->nValues > 0)) || - (ops->xError && ops->xError->nValues > 0) || - (ops->yError && ops->yError->nValues > 0)) { - MapErrorBars(graphPtr, lePtr, styleMap); - } - - MergePens(lePtr, styleMap); - free(styleMap); -} - -static double DistanceToLineProc(int x, int y, Point2d *p, Point2d *q, - Point2d *t) -{ - double right, left, top, bottom; - - *t = Blt_GetProjection(x, y, p, q); - if (p->x > q->x) { - right = p->x, left = q->x; - } else { - left = p->x, right = q->x; - } - if (p->y > q->y) { - bottom = p->y, top = q->y; - } else { - top = p->y, bottom = q->y; - } - if (t->x > right) { - t->x = right; - } else if (t->x < left) { - t->x = left; - } - if (t->y > bottom) { - t->y = bottom; - } else if (t->y < top) { - t->y = top; - } - return hypot((t->x - x), (t->y - y)); -} - -static double DistanceToXProc(int x, int y, Point2d *p, Point2d *q, - Point2d *t) -{ - double dx, dy; - double d; - - if (p->x > q->x) { - if ((x > p->x) || (x < q->x)) { - return DBL_MAX; /* X-coordinate outside line segment. */ - } - } else { - if ((x > q->x) || (x < p->x)) { - return DBL_MAX; /* X-coordinate outside line segment. */ - } - } - dx = p->x - q->x; - dy = p->y - q->y; - t->x = (double)x; - if (fabs(dx) < DBL_EPSILON) { - double d1, d2; - /* - * Same X-coordinate indicates a vertical line. Pick the closest end - * point. - */ - d1 = p->y - y; - d2 = q->y - y; - if (fabs(d1) < fabs(d2)) { - t->y = p->y, d = d1; - } else { - t->y = q->y, d = d2; - } - } else if (fabs(dy) < DBL_EPSILON) { - /* Horizontal line. */ - t->y = p->y, d = p->y - y; - } else { - double m, b; - - m = dy / dx; - b = p->y - (m * p->x); - t->y = (x * m) + b; - d = y - t->y; - } - return fabs(d); -} - -static double DistanceToYProc(int x, int y, Point2d *p, Point2d *q, Point2d *t) -{ - double dx, dy; - double d; - - if (p->y > q->y) { - if ((y > p->y) || (y < q->y)) { - return DBL_MAX; - } - } else { - if ((y > q->y) || (y < p->y)) { - return DBL_MAX; - } - } - dx = p->x - q->x; - dy = p->y - q->y; - t->y = y; - if (fabs(dy) < DBL_EPSILON) { - double d1, d2; - - /* Save Y-coordinate indicates an horizontal line. Pick the closest end - * point. */ - d1 = p->x - x; - d2 = q->x - x; - if (fabs(d1) < fabs(d2)) { - t->x = p->x, d = d1; - } else { - t->x = q->x, d = d2; - } - } else if (fabs(dx) < DBL_EPSILON) { - /* Vertical line. */ - t->x = p->x, d = p->x - x; - } else { - double m, b; - - m = dy / dx; - b = p->y - (m * p->x); - t->x = (y - b) / m; - d = x - t->x; + yeb_.segments = errorBars; + yeb_.length = segPtr - errorBars; + yeb_.map = errorToData; } - return fabs(d); } -static int ClosestTrace(Graph* graphPtr, LineElement* lePtr, - DistanceProc *distProc) +int LineElement::ClosestTrace() { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - ClosestSearch* searchPtr = &graphPtr->search; + LineElementOptions* ops = (LineElementOptions*)ops; + ClosestSearch* searchPtr = &graphPtr_->search; Blt_ChainLink link; Point2d closest; @@ -1608,7 +1993,7 @@ static int ClosestTrace(Graph* graphPtr, LineElement* lePtr, iClose = -1; /* Suppress compiler warning. */ dMin = searchPtr->dist; closest.x = closest.y = 0; /* Suppress compiler warning. */ - for (link = Blt_Chain_FirstLink(lePtr->traces); link; + for (link = Blt_Chain_FirstLink(traces_); link; link = Blt_Chain_NextLink(link)) { Point2d *p, *pend; @@ -1618,7 +2003,13 @@ static int ClosestTrace(Graph* graphPtr, LineElement* lePtr, Point2d b; double d; - d = (*distProc)(searchPtr->x, searchPtr->y, p, p + 1, &b); + if (search->along == SEARCH_X) + d = DistanceToX(searchPtr->x, searchPtr->y, p, p + 1, &b); + else if (search->along == SEARCH_Y) + d = DistanceToY(searchPtr->x, searchPtr->y, p, p + 1, &b); + else + d = DistanceToLine(searchPtr->x, searchPtr->y, p, p + 1, &b); + if (d < dMin) { closest = b; iClose = tracePtr->screenPts.map[p-tracePtr->screenPts.points]; @@ -1628,17 +2019,18 @@ static int ClosestTrace(Graph* graphPtr, LineElement* lePtr, } if (dMin < searchPtr->dist) { searchPtr->dist = dMin; - searchPtr->elemPtr = (Element*)lePtr; + searchPtr->elemPtr = (Element*)this; searchPtr->index = iClose; - searchPtr->point = Blt_InvMap2D(graphPtr, closest.x, closest.y, &ops->axes); + searchPtr->point = Blt_InvMap2D(graphPtr_, closest.x, closest.y, &ops->axes); return 1; } + return 0; } -static void ClosestPoint(LineElement* lePtr, ClosestSearch *searchPtr) +void LineElement::ClosestPoint(ClosestSearch *searchPtr) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; double dMin = searchPtr->dist; int iClose = 0; @@ -1649,8 +2041,8 @@ static void ClosestPoint(LineElement* lePtr, ClosestSearch *searchPtr) // 2) the computed distance is already in screen coordinates. int count; Point2d *pp; - for (pp = lePtr->symbolPts.points, count = 0; - count < lePtr->symbolPts.length; count++, pp++) { + for (pp = symbolPts_.points, count = 0; + count < symbolPts_.length; count++, pp++) { double dx = (double)(searchPtr->x - pp->x); double dy = (double)(searchPtr->y - pp->y); double d; @@ -1664,12 +2056,12 @@ static void ClosestPoint(LineElement* lePtr, ClosestSearch *searchPtr) continue; if (d < dMin) { - iClose = lePtr->symbolPts.map[count]; + iClose = symbolPts_.map[count]; dMin = d; } } if (dMin < searchPtr->dist) { - searchPtr->elemPtr = (Element*)lePtr; + searchPtr->elemPtr = (Element*)this; searchPtr->dist = dMin; searchPtr->index = iClose; searchPtr->point.x = ops->coords.x->values[iClose]; @@ -1677,152 +2069,6 @@ static void ClosestPoint(LineElement* lePtr, ClosestSearch *searchPtr) } } -static void GetLineExtentsProc(Element *elemPtr, Region2d *extsPtr) -{ - LineElement* lePtr = (LineElement *)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - extsPtr->top = extsPtr->left = DBL_MAX; - extsPtr->bottom = extsPtr->right = -DBL_MAX; - - if (!ops->coords.x || !ops->coords.y || - !ops->coords.x->nValues || !ops->coords.y->nValues) - return; - int np = NUMBEROFPOINTS(ops); - - extsPtr->right = ops->coords.x->max; - if ((ops->coords.x->min <= 0.0) && (ops->axes.x->logScale)) - extsPtr->left = Blt_FindElemValuesMinimum(ops->coords.x, DBL_MIN); - else - extsPtr->left = ops->coords.x->min; - - extsPtr->bottom = ops->coords.y->max; - if ((ops->coords.y->min <= 0.0) && (ops->axes.y->logScale)) - extsPtr->top = Blt_FindElemValuesMinimum(ops->coords.y, DBL_MIN); - else - extsPtr->top = ops->coords.y->min; - - // Correct the data limits for error bars - if (ops->xError && ops->xError->nValues > 0) { - int i; - - np = MIN(ops->xError->nValues, np); - for (i = 0; i < np; i++) { - double x; - - x = ops->coords.x->values[i] + ops->xError->values[i]; - if (x > extsPtr->right) { - extsPtr->right = x; - } - x = ops->coords.x->values[i] - ops->xError->values[i]; - if (ops->axes.x->logScale) { - // Mirror negative values, instead of ignoring them - if (x < 0.0) - x = -x; - if ((x > DBL_MIN) && (x < extsPtr->left)) - extsPtr->left = x; - } - else if (x < extsPtr->left) - extsPtr->left = x; - } - } - else { - if (ops->xHigh && - (ops->xHigh->nValues > 0) && - (ops->xHigh->max > extsPtr->right)) { - extsPtr->right = ops->xHigh->max; - } - if (ops->xLow && ops->xLow->nValues > 0) { - double left; - - if ((ops->xLow->min <= 0.0) && - (ops->axes.x->logScale)) - left = Blt_FindElemValuesMinimum(ops->xLow, DBL_MIN); - else - left = ops->xLow->min; - - if (left < extsPtr->left) - extsPtr->left = left; - } - } - - if (ops->yError && ops->yError->nValues > 0) { - int i; - - np = MIN(ops->yError->nValues, np); - for (i = 0; i < np; i++) { - double y; - - y = ops->coords.y->values[i] + ops->yError->values[i]; - if (y > extsPtr->bottom) { - extsPtr->bottom = y; - } - y = ops->coords.y->values[i] - ops->yError->values[i]; - if (ops->axes.y->logScale) { - if (y < 0.0) { - y = -y; /* Mirror negative values, instead of - * ignoring them. */ - } - if ((y > DBL_MIN) && (y < extsPtr->left)) { - extsPtr->top = y; - } - } else if (y < extsPtr->top) { - extsPtr->top = y; - } - } - } else { - if (ops->yHigh && - (ops->yHigh->nValues > 0) && - (ops->yHigh->max > extsPtr->bottom)) { - extsPtr->bottom = ops->yHigh->max; - } - if (ops->yLow && ops->yLow->nValues > 0) { - double top; - - if ((ops->yLow->min <= 0.0) && - (ops->axes.y->logScale)) - top = Blt_FindElemValuesMinimum(ops->yLow, DBL_MIN); - else - top = ops->yLow->min; - - if (top < extsPtr->top) - extsPtr->top = top; - } - } -} - -static void ClosestLineProc(Graph* graphPtr, Element *elemPtr) -{ - LineElement* lePtr = (LineElement*)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - ClosestSearch* searchPtr = &graphPtr->search; - int mode = searchPtr->mode; - if (mode == SEARCH_AUTO) { - LinePen* penPtr = NORMALPEN(ops); - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - mode = SEARCH_POINTS; - if ((NUMBEROFPOINTS(ops) > 1) && (penOps->traceWidth > 0)) - mode = SEARCH_TRACES; - } - if (mode == SEARCH_POINTS) - ClosestPoint(lePtr, searchPtr); - else { - DistanceProc *distProc; - if (searchPtr->along == SEARCH_X) - distProc = DistanceToXProc; - else if (searchPtr->along == SEARCH_Y) - distProc = DistanceToYProc; - else - distProc = DistanceToLineProc; - - int found = ClosestTrace(graphPtr, lePtr, distProc); - if ((!found) && (searchPtr->along != SEARCH_BOTH)) { - ClosestPoint(lePtr, searchPtr); - } - } -} - /* * XDrawLines() points: XMaxRequestSize(dpy) - 3 * XFillPolygon() points: XMaxRequestSize(dpy) - 4 @@ -1838,8 +2084,8 @@ static void ClosestLineProc(Graph* graphPtr, Element *elemPtr) #define MAX_DRAWRECTANGLES(d) Blt_MaxRequestSize(d, sizeof(XRectangle)) #define MAX_DRAWARCS(d) Blt_MaxRequestSize(d, sizeof(XArc)) -static void DrawCircles(Display *display, Drawable drawable, - LineElement* lePtr, LinePen* penPtr, +void LineElement::DrawCircles(Display *display, Drawable drawable, + LinePen* penPtr, int nSymbolPts, Point2d *symbolPts, int radius) { LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); @@ -1848,7 +2094,7 @@ static void DrawCircles(Display *display, Drawable drawable, int s = radius + radius; XArc *arcs = (XArc*)malloc(nSymbolPts * sizeof(XArc)); - if (lePtr->symbolInterval > 0) { + if (symbolInterval > 0) { XArc* ap = arcs; Point2d *pp, *pend; for (pp = symbolPts, pend = pp + nSymbolPts; pp < pend; pp++) { @@ -1860,7 +2106,7 @@ static void DrawCircles(Display *display, Drawable drawable, ap->angle2 = 23040; ap++, count++; } - lePtr->symbolCounter++; + symbolCounter++; } } else { @@ -1890,9 +2136,9 @@ static void DrawCircles(Display *display, Drawable drawable, free(arcs); } -static void DrawSquares(Display *display, Drawable drawable, - LineElement* lePtr, LinePen* penPtr, - int nSymbolPts, Point2d *symbolPts, int r) +void LineElement::DrawSquares(Display *display, Drawable drawable, + LinePen* penPtr, + int nSymbolPts, Point2d *symbolPts, int r) { LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); @@ -1900,7 +2146,7 @@ static void DrawSquares(Display *display, Drawable drawable, int s = r + r; XRectangle *rectangles = (XRectangle*)malloc(nSymbolPts * sizeof(XRectangle)); - if (lePtr->symbolInterval > 0) { + if (symbolInterval > 0) { XRectangle* rp = rectangles; Point2d *pp, *pend; for (pp = symbolPts, pend = pp + nSymbolPts; pp < pend; pp++) { @@ -1910,7 +2156,7 @@ static void DrawSquares(Display *display, Drawable drawable, rp->width = rp->height = (unsigned short)s; rp++, count++; } - lePtr->symbolCounter++; + symbolCounter++; } } else { @@ -1944,9 +2190,8 @@ static void DrawSquares(Display *display, Drawable drawable, #define SQRT_PI 1.77245385090552 #define S_RATIO 0.886226925452758 -static void DrawSymbols(Graph* graphPtr, Drawable drawable, - LineElement* lePtr, LinePen* penPtr, - int size, int nSymbolPts, Point2d *symbolPts) +void LineElement::DrawSymbols(Drawable drawable, LinePen* penPtr, + int size, int nSymbolPts, Point2d *symbolPts) { LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); @@ -1963,7 +2208,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, xpp->y = Round(pp->y); xpp++; } - XDrawPoints(graphPtr->display, drawable, penOps->symbol.fillGC, + XDrawPoints(graphPtr_->display, drawable, penOps->symbol.fillGC, points, nSymbolPts, CoordModeOrigin); free(points); } @@ -1978,12 +2223,12 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, break; case SYMBOL_SQUARE: - DrawSquares(graphPtr->display, drawable, lePtr, penPtr, nSymbolPts, + DrawSquares(graphPtr_->display, drawable, lePtr, penPtr, nSymbolPts, symbolPts, r2); break; case SYMBOL_CIRCLE: - DrawCircles(graphPtr->display, drawable, lePtr, penPtr, nSymbolPts, + DrawCircles(graphPtr_->display, drawable, lePtr, penPtr, nSymbolPts, symbolPts, r1); break; @@ -2002,7 +2247,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, } XSegment *segments = (XSegment*)malloc(nSymbolPts * 2 * sizeof(XSegment)); - if (lePtr->symbolInterval > 0) { + if (symbolInterval > 0) { XSegment* sp = segments; count = 0; Point2d *pp, *endp; @@ -2022,7 +2267,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, sp++; count++; } - lePtr->symbolCounter++; + symbolCounter++; } } else { @@ -2046,10 +2291,10 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, } int nSegs = count * 2; // Always draw skinny symbols regardless of the outline width - int reqSize = MAX_DRAWSEGMENTS(graphPtr->display); + int reqSize = MAX_DRAWSEGMENTS(graphPtr_->display); for (int ii=0; ii<nSegs; ii+=reqSize) { int chunk = ((ii + reqSize) > nSegs) ? (nSegs - ii) : reqSize; - XDrawSegments(graphPtr->display, drawable, + XDrawSegments(graphPtr_->display, drawable, penOps->symbol.outlineGC, segments + ii, chunk); } free(segments); @@ -2097,7 +2342,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, pattern[12] = pattern[0]; } polygon = (XPoint*)malloc(nSymbolPts * 13 * sizeof(XPoint)); - if (lePtr->symbolInterval > 0) { + if (symbolInterval > 0) { count = 0; XPoint* xpp = polygon; Point2d *pp, *endp; @@ -2112,7 +2357,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, } count++; } - lePtr->symbolCounter++; + symbolCounter++; } } else { @@ -2133,7 +2378,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, int ii; XPoint *xpp; for (xpp = polygon, ii = 0; ii<count; ii++, xpp += 13) - XFillPolygon(graphPtr->display, drawable, + XFillPolygon(graphPtr_->display, drawable, penOps->symbol.fillGC, xpp, 13, Complex, CoordModeOrigin); } @@ -2141,7 +2386,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, int ii; XPoint *xpp; for (xpp = polygon, ii=0; ii<count; ii++, xpp += 13) - XDrawLines(graphPtr->display, drawable, + XDrawLines(graphPtr_->display, drawable, penOps->symbol.outlineGC, xpp, 13, CoordModeOrigin); } free(polygon); @@ -2168,7 +2413,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, pattern[4] = pattern[0]; polygon = (XPoint*)malloc(nSymbolPts * 5 * sizeof(XPoint)); - if (lePtr->symbolInterval > 0) { + if (symbolInterval > 0) { Point2d *pp, *endp; XPoint *xpp; @@ -2188,7 +2433,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, } count++; } - lePtr->symbolCounter++; + symbolCounter++; } } else { Point2d *pp, *endp; @@ -2213,7 +2458,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, int i; for (xpp = polygon, i = 0; i < count; i++, xpp += 5) - XFillPolygon(graphPtr->display, drawable, + XFillPolygon(graphPtr_->display, drawable, penOps->symbol.fillGC, xpp, 5, Convex, CoordModeOrigin); } if (penOps->symbol.outlineWidth > 0) { @@ -2221,7 +2466,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, int i; for (xpp = polygon, i = 0; i < count; i++, xpp += 5) { - XDrawLines(graphPtr->display, drawable, + XDrawLines(graphPtr_->display, drawable, penOps->symbol.outlineGC, xpp, 5, CoordModeOrigin); } } @@ -2269,7 +2514,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, pattern[2].x = -b2; } polygon = (XPoint*)malloc(nSymbolPts * 4 * sizeof(XPoint)); - if (lePtr->symbolInterval > 0) { + if (symbolInterval > 0) { Point2d *pp, *endp; XPoint *xpp; @@ -2289,7 +2534,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, } count++; } - lePtr->symbolCounter++; + symbolCounter++; } } else { Point2d *pp, *endp; @@ -2315,7 +2560,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, xpp = polygon; for (xpp = polygon, i = 0; i < count; i++, xpp += 4) - XFillPolygon(graphPtr->display, drawable, + XFillPolygon(graphPtr_->display, drawable, penOps->symbol.fillGC, xpp, 4, Convex, CoordModeOrigin); } if (penOps->symbol.outlineWidth > 0) { @@ -2324,7 +2569,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, xpp = polygon; for (xpp = polygon, i = 0; i < count; i++, xpp += 4) { - XDrawLines(graphPtr->display, drawable, + XDrawLines(graphPtr_->display, drawable, penOps->symbol.outlineGC, xpp, 4, CoordModeOrigin); } } @@ -2338,7 +2583,7 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, double scale, sx, sy; int dx, dy; - Tk_SizeOfBitmap(graphPtr->display, penOps->symbol.bitmap, &w, &h); + Tk_SizeOfBitmap(graphPtr_->display, penOps->symbol.bitmap, &w, &h); // Compute the size of the scaled bitmap. Stretch the bitmap to fit // a nxn bounding box. @@ -2348,19 +2593,19 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, bw = (int)(w * scale); bh = (int)(h * scale); - XSetClipMask(graphPtr->display, penOps->symbol.outlineGC, None); + XSetClipMask(graphPtr_->display, penOps->symbol.outlineGC, None); if (penOps->symbol.mask != None) - XSetClipMask(graphPtr->display, penOps->symbol.outlineGC, + XSetClipMask(graphPtr_->display, penOps->symbol.outlineGC, penOps->symbol.mask); if (penOps->symbol.fillGC == NULL) - XSetClipMask(graphPtr->display, penOps->symbol.outlineGC, + XSetClipMask(graphPtr_->display, penOps->symbol.outlineGC, penOps->symbol.bitmap); dx = bw / 2; dy = bh / 2; - if (lePtr->symbolInterval > 0) { + if (symbolInterval > 0) { Point2d *pp, *endp; for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) { if (DRAW_SYMBOL(lePtr)) { @@ -2368,12 +2613,12 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, int y = Round(pp->y) - dy; if ((penOps->symbol.fillGC == NULL) || (penOps->symbol.mask != None)) - XSetClipOrigin(graphPtr->display, + XSetClipOrigin(graphPtr_->display, penOps->symbol.outlineGC, x, y); - XCopyPlane(graphPtr->display, penOps->symbol.bitmap, drawable, + XCopyPlane(graphPtr_->display, penOps->symbol.bitmap, drawable, penOps->symbol.outlineGC, 0, 0, bw, bh, x, y, 1); } - lePtr->symbolCounter++; + symbolCounter++; } } else { @@ -2383,9 +2628,9 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, int y = Round(pp->y) - dy; if ((penOps->symbol.fillGC == NULL) || (penOps->symbol.mask != None)) - XSetClipOrigin(graphPtr->display, + XSetClipOrigin(graphPtr_->display, penOps->symbol.outlineGC, x, y); - XCopyPlane(graphPtr->display, penOps->symbol.bitmap, drawable, + XCopyPlane(graphPtr_->display, penOps->symbol.bitmap, drawable, penOps->symbol.outlineGC, 0, 0, bw, bh, x, y, 1); } } @@ -2394,48 +2639,15 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, } } -static void DrawSymbolProc(Graph* graphPtr, Drawable drawable, - Element *elemPtr, int x, int y, int size) -{ - LineElement* lePtr = (LineElement *)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - LinePen* penPtr = NORMALPEN(ops); - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - - if (penOps->traceWidth > 0) { - /* - * Draw an extra line offset by one pixel from the previous to give a - * thicker appearance. This is only for the legend entry. This routine - * is never called for drawing the actual line segments. - */ - XDrawLine(graphPtr->display, drawable, penPtr->traceGC_, x - size, y, - x + size, y); - XDrawLine(graphPtr->display, drawable, penPtr->traceGC_, x - size, y + 1, - x + size, y + 1); - } - if (penOps->symbol.type != SYMBOL_NONE) { - Point2d point; - - point.x = x, point.y = y; - DrawSymbols(graphPtr, drawable, lePtr, penPtr, size, 1, &point); - } -} - -static void DrawTraces(Graph* graphPtr, Drawable drawable, - LineElement* lePtr, LinePen* penPtr) +void LineElement::DrawTraces(Drawable drawable, LinePen* penPtr) { - Blt_ChainLink link; - int np; - - np = Blt_MaxRequestSize(graphPtr->display, sizeof(XPoint)) - 1; + int np = Blt_MaxRequestSize(graphPtr_->display, sizeof(XPoint)) - 1; XPoint *points = (XPoint*)malloc((np + 1) * sizeof(XPoint)); - for (link = Blt_Chain_FirstLink(lePtr->traces); link; + for (Blt_ChainLink link = Blt_Chain_FirstLink(traces); link; link = Blt_Chain_NextLink(link)) { XPoint *xpp; int remaining, count; - int n; bltTrace *tracePtr = (bltTrace*)Blt_Chain_GetValue(link); @@ -2447,12 +2659,12 @@ static void DrawTraces(Graph* graphPtr, Drawable drawable, /* Step 1. Convert and draw the first section of the trace. * It may contain the entire trace. */ - n = MIN(np, tracePtr->screenPts.length); + int n = MIN(np, tracePtr->screenPts.length); for (xpp = points, count = 0; count < n; count++, xpp++) { xpp->x = Round(tracePtr->screenPts.points[count].x); xpp->y = Round(tracePtr->screenPts.points[count].y); } - XDrawLines(graphPtr->display, drawable, penPtr->traceGC_, points, + XDrawLines(graphPtr_->display, drawable, penPtr->traceGC_, points, count, CoordModeOrigin); /* Step 2. Next handle any full-size chunks left. */ @@ -2468,7 +2680,7 @@ static void DrawTraces(Graph* graphPtr, Drawable drawable, xpp->x = Round(tracePtr->screenPts.points[count].x); xpp->y = Round(tracePtr->screenPts.points[count].y); } - XDrawLines(graphPtr->display, drawable, penPtr->traceGC_, points, + XDrawLines(graphPtr_->display, drawable, penPtr->traceGC_, points, np + 1, CoordModeOrigin); } @@ -2484,205 +2696,53 @@ static void DrawTraces(Graph* graphPtr, Drawable drawable, xpp->x = Round(tracePtr->screenPts.points[count].x); xpp->y = Round(tracePtr->screenPts.points[count].y); } - XDrawLines(graphPtr->display, drawable, penPtr->traceGC_, points, + XDrawLines(graphPtr_->display, drawable, penPtr->traceGC_, points, remaining + 1, CoordModeOrigin); } } free(points); } -static void DrawValues(Graph* graphPtr, Drawable drawable, - LineElement* lePtr, LinePen* penPtr, - int length, Point2d *points, int *map) +void LineElement::DrawValues(Drawable drawable, LinePen* penPtr, + int length, Point2d *points, int *map) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); Point2d *pp, *endp; double *xval, *yval; const char* fmt; char string[TCL_DOUBLE_SPACE * 2 + 2]; - int count; fmt = penOps->valueFormat; if (fmt == NULL) fmt = "%g"; - count = 0; + int count = 0; xval = ops->coords.x->values, yval = ops->coords.y->values; // be sure to update style->gc, things might have changed penOps->valueStyle.flags |= UPDATE_GC; for (pp = points, endp = points + length; pp < endp; pp++) { - double x, y; - - x = xval[map[count]]; - y = yval[map[count]]; + double x = xval[map[count]]; + double y = yval[map[count]]; count++; - if (penOps->valueShow == SHOW_X) { + if (penOps->valueShow == SHOW_X) sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x); - } else if (penOps->valueShow == SHOW_Y) { + else if (penOps->valueShow == SHOW_Y) sprintf_s(string, TCL_DOUBLE_SPACE, fmt, y); - } else if (penOps->valueShow == SHOW_BOTH) { + else if (penOps->valueShow == SHOW_BOTH) { sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x); strcat(string, ","); sprintf_s(string + strlen(string), TCL_DOUBLE_SPACE, fmt, y); } - Blt_DrawText(graphPtr->tkwin, drawable, string, &penOps->valueStyle, + + Blt_DrawText(graphPtr_->tkwin, drawable, string, &penOps->valueStyle, Round(pp->x), Round(pp->y)); } } -static void DrawActiveLineProc(Graph* graphPtr, Drawable drawable, - Element *elemPtr) -{ - LineElement* lePtr = (LineElement *)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - LinePen* penPtr = (LinePen *)ops->activePenPtr; - - if (!penPtr) - return; - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - - int symbolSize = ScaleSymbol(lePtr, penOps->symbol.size); - - /* - * nActiveIndices - * > 0 Some points are active. Uses activeArr. - * < 0 All points are active. - * == 0 No points are active. - */ - if (lePtr->nActiveIndices > 0) { - if (lePtr->flags & ACTIVE_PENDING) { - MapActiveSymbols(graphPtr, lePtr); - } - if (penOps->symbol.type != SYMBOL_NONE) { - DrawSymbols(graphPtr, drawable, lePtr, penPtr, symbolSize, - lePtr->activePts.length, lePtr->activePts.points); - } - if (penOps->valueShow != SHOW_NONE) { - DrawValues(graphPtr, drawable, lePtr, penPtr, - lePtr->activePts.length, - lePtr->activePts.points, - lePtr->activePts.map); - } - } else if (lePtr->nActiveIndices < 0) { - if (penOps->traceWidth > 0) { - if (lePtr->lines.length > 0) { - Blt_Draw2DSegments(graphPtr->display, drawable, - penPtr->traceGC_, lePtr->lines.segments, - lePtr->lines.length); - } else if (Blt_Chain_GetLength(lePtr->traces) > 0) { - DrawTraces(graphPtr, drawable, lePtr, penPtr); - } - } - if (penOps->symbol.type != SYMBOL_NONE) { - DrawSymbols(graphPtr, drawable, lePtr, penPtr, symbolSize, - lePtr->symbolPts.length, lePtr->symbolPts.points); - } - if (penOps->valueShow != SHOW_NONE) { - DrawValues(graphPtr, drawable, lePtr, penPtr, - lePtr->symbolPts.length, lePtr->symbolPts.points, - lePtr->symbolPts.map); - } - } -} - -static void DrawNormalLineProc(Graph* graphPtr, Drawable drawable, - Element *elemPtr) -{ - LineElement* lePtr = (LineElement *)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - // Fill area under the curve - if (lePtr->fillPts) { - XPoint *points = (XPoint*)malloc(sizeof(XPoint) * lePtr->nFillPts); - - unsigned int count =0; - Point2d *endp, *pp; - for (pp = lePtr->fillPts, endp = pp + lePtr->nFillPts; - pp < endp; pp++) { - points[count].x = Round(pp->x); - points[count].y = Round(pp->y); - count++; - } - if (ops->fillBg) - Tk_Fill3DPolygon(graphPtr->tkwin, drawable, ops->fillBg, points, - lePtr->nFillPts, 0, TK_RELIEF_FLAT); - free(points); - } - - // Lines: stripchart segments or graph traces - if (lePtr->lines.length > 0) { - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); - link; link = Blt_Chain_NextLink(link)) { - - LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); - LinePen* penPtr = (LinePen *)stylePtr->penPtr; - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - if ((stylePtr->lines.length > 0) && - (penOps->errorBarLineWidth > 0)) { - Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->traceGC_, - stylePtr->lines.segments, stylePtr->lines.length); - } - } - } - else { - LinePen* penPtr = NORMALPEN(ops); - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - - if ((Blt_Chain_GetLength(lePtr->traces) > 0) && - (penOps->traceWidth > 0)) { - DrawTraces(graphPtr, drawable, lePtr, penPtr); - } - } - - if (ops->reqMaxSymbols > 0) { - int total = 0; - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); - link; link = Blt_Chain_NextLink(link)) { - LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); - total += stylePtr->symbolPts.length; - } - lePtr->symbolInterval = total / ops->reqMaxSymbols; - lePtr->symbolCounter = 0; - } - - // Symbols, error bars, values - - unsigned int count =0; - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; - link = Blt_Chain_NextLink(link)) { - LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); - LinePen* penPtr = (LinePen *)stylePtr->penPtr; - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - - if ((stylePtr->xeb.length > 0) && (penOps->errorBarShow & SHOW_X)) - Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC_, - stylePtr->xeb.segments, stylePtr->xeb.length); - - if ((stylePtr->yeb.length > 0) && (penOps->errorBarShow & SHOW_Y)) - Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC_, - stylePtr->yeb.segments, stylePtr->yeb.length); - - if ((stylePtr->symbolPts.length > 0) && - (penOps->symbol.type != SYMBOL_NONE)) - DrawSymbols(graphPtr, drawable, lePtr, penPtr, - stylePtr->symbolSize, stylePtr->symbolPts.length, - stylePtr->symbolPts.points); - - if (penOps->valueShow != SHOW_NONE) - DrawValues(graphPtr, drawable, lePtr, penPtr, - stylePtr->symbolPts.length, stylePtr->symbolPts.points, - lePtr->symbolPts.map + count); - - count += stylePtr->symbolPts.length; - } - lePtr->symbolInterval = 0; -} - -static void GetSymbolPostScriptInfo(Graph* graphPtr, Blt_Ps ps, - LinePen* penPtr, int size) +void GetSymbolPostScriptInfo(Blt_Ps ps, LinePen* penPtr, int size) { LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); @@ -2721,24 +2781,24 @@ static void GetSymbolPostScriptInfo(Graph* graphPtr, Blt_Ps ps, * Compute how much to scale the bitmap. Don't let the scaled * bitmap exceed the bounding square for the symbol. */ - Tk_SizeOfBitmap(graphPtr->display, penOps->symbol.bitmap, &w, &h); + Tk_SizeOfBitmap(graphPtr_->display, penOps->symbol.bitmap, &w, &h); sx = (double)size / (double)w; sy = (double)size / (double)h; scale = MIN(sx, sy); if (penOps->symbol.mask != None) { Blt_Ps_VarAppend(ps, "\n % Bitmap mask is \"", - Tk_NameOfBitmap(graphPtr->display, penOps->symbol.mask), + Tk_NameOfBitmap(graphPtr_->display, penOps->symbol.mask), "\"\n\n ", NULL); Blt_Ps_XSetBackground(ps, fillColor); - Blt_Ps_DrawBitmap(ps, graphPtr->display, penOps->symbol.mask, + Blt_Ps_DrawBitmap(ps, graphPtr_->display, penOps->symbol.mask, scale, scale); } Blt_Ps_VarAppend(ps, "\n % Bitmap symbol is \"", - Tk_NameOfBitmap(graphPtr->display, penOps->symbol.bitmap), + Tk_NameOfBitmap(graphPtr_->display, penOps->symbol.bitmap), "\"\n\n ", NULL); Blt_Ps_XSetForeground(ps, outlineColor); - Blt_Ps_DrawBitmap(ps, graphPtr->display, penOps->symbol.bitmap, + Blt_Ps_DrawBitmap(ps, graphPtr_->display, penOps->symbol.bitmap, scale, scale); } break; @@ -2757,8 +2817,8 @@ static void GetSymbolPostScriptInfo(Graph* graphPtr, Blt_Ps ps, Blt_Ps_Append(ps, "} def\n\n"); } -static void SymbolsToPostScript(Graph* graphPtr, Blt_Ps ps, LinePen* penPtr, - int size, int nSymbolPts, Point2d *symbolPts) +void LineElement::SymbolsToPostScript(Blt_Ps ps, LinePen* penPtr, int size, + int nSymbolPts, Point2d *symbolPts) { LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); @@ -2767,7 +2827,7 @@ static void SymbolsToPostScript(Graph* graphPtr, Blt_Ps ps, LinePen* penPtr, { "Li", "Sq", "Ci", "Di", "Pl", "Cr", "Sp", "Sc", "Tr", "Ar", "Bm", NULL }; - GetSymbolPostScriptInfo(graphPtr, ps, penPtr, size); + GetSymbolPostScriptInfo(graphPtr_, ps, penPtr, size); symbolSize = (double)size; switch (penOps->symbol.type) { @@ -2789,45 +2849,15 @@ static void SymbolsToPostScript(Graph* graphPtr, Blt_Ps ps, LinePen* penPtr, default: break; } - { - Point2d *pp, *endp; - - for (pp = symbolPts, endp = symbolPts + nSymbolPts; pp < endp; pp++) { - Blt_Ps_Format(ps, "%g %g %g %s\n", pp->x, pp->y, - symbolSize, symbolMacros[penOps->symbol.type]); - } - } -} - -static void SymbolToPostScriptProc(Graph* graphPtr, Blt_Ps ps, - Element *elemPtr, double x, double y, - int size) -{ - LineElement* lePtr = (LineElement *)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - LinePen* penPtr = NORMALPEN(ops); - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - - if (penOps->traceWidth > 0) { - /* - * Draw an extra line offset by one pixel from the previous to give a - * thicker appearance. This is only for the legend entry. This routine - * is never called for drawing the actual line segments. - */ - Blt_Ps_XSetLineAttributes(ps, penOps->traceColor, penOps->traceWidth, - &penOps->traceDashes, CapButt, JoinMiter); - Blt_Ps_Format(ps, "%g %g %d Li\n", x, y, size + size); - } - if (penOps->symbol.type != SYMBOL_NONE) { - Point2d point; - point.x = x, point.y = y; - SymbolsToPostScript(graphPtr, ps, penPtr, size, 1, &point); + Point2d *pp, *endp; + for (pp = symbolPts, endp = symbolPts + nSymbolPts; pp < endp; pp++) { + Blt_Ps_Format(ps, "%g %g %g %s\n", pp->x, pp->y, + symbolSize, symbolMacros[penOps->symbol.type]); } } -static void SetLineAttributes(Blt_Ps ps, LinePen* penPtr) +void LineElement::SetLineAttributes(Blt_Ps ps, LinePen* penPtr) { LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); @@ -2846,12 +2876,10 @@ static void SetLineAttributes(Blt_Ps ps, LinePen* penPtr) } } -static void TracesToPostScript(Blt_Ps ps, LineElement* lePtr, LinePen* penPtr) +void LineElement::TracesToPostScript(Blt_Ps ps, LinePen* penPtr) { - Blt_ChainLink link; - SetLineAttributes(ps, penPtr); - for (link = Blt_Chain_FirstLink(lePtr->traces); link; + for (Blt_ChainLink link = Blt_Chain_FirstLink(traces); link; link = Blt_Chain_NextLink(link)) { bltTrace *tracePtr = (bltTrace*)Blt_Chain_GetValue(link); if (tracePtr->screenPts.length > 0) { @@ -2863,11 +2891,11 @@ static void TracesToPostScript(Blt_Ps ps, LineElement* lePtr, LinePen* penPtr) } } -static void ValuesToPostScript(Blt_Ps ps, LineElement* lePtr, LinePen* penPtr, - int nSymbolPts, Point2d *symbolPts, - int *pointToData) +void LineElement::ValuesToPostScript(Blt_Ps ps, LinePen* penPtr, + int nSymbolPts, Point2d *symbolPts, + int *pointToData) { - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; + LineElementOptions* ops = (LineElementOptions*)ops; LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); const char* fmt = penOps->valueFormat; @@ -2897,144 +2925,4 @@ static void ValuesToPostScript(Blt_Ps ps, LineElement* lePtr, LinePen* penPtr, } } -static void ActiveLineToPostScriptProc(Graph* graphPtr, Blt_Ps ps, - Element *elemPtr) -{ - LineElement* lePtr = (LineElement *)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - LinePen* penPtr = (LinePen *)ops->activePenPtr; - if (!penPtr) - return; - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - - int symbolSize = ScaleSymbol(lePtr, penOps->symbol.size); - if (lePtr->nActiveIndices > 0) { - if (lePtr->flags & ACTIVE_PENDING) { - MapActiveSymbols(graphPtr, lePtr); - } - if (penOps->symbol.type != SYMBOL_NONE) { - SymbolsToPostScript(graphPtr, ps, penPtr, symbolSize, - lePtr->activePts.length, lePtr->activePts.points); - } - if (penOps->valueShow != SHOW_NONE) { - ValuesToPostScript(ps, lePtr, penPtr, lePtr->activePts.length, - lePtr->activePts.points, lePtr->activePts.map); - } - } - else if (lePtr->nActiveIndices < 0) { - if (penOps->traceWidth > 0) { - if (lePtr->lines.length > 0) { - SetLineAttributes(ps, penPtr); - Blt_Ps_Draw2DSegments(ps, lePtr->lines.segments, - lePtr->lines.length); - } - if (Blt_Chain_GetLength(lePtr->traces) > 0) { - TracesToPostScript(ps, lePtr, (LinePen *)penPtr); - } - } - if (penOps->symbol.type != SYMBOL_NONE) { - SymbolsToPostScript(graphPtr, ps, penPtr, symbolSize, - lePtr->symbolPts.length, lePtr->symbolPts.points); - } - if (penOps->valueShow != SHOW_NONE) { - ValuesToPostScript(ps, lePtr, penPtr, lePtr->symbolPts.length, - lePtr->symbolPts.points, lePtr->symbolPts.map); - } - } -} - -static void NormalLineToPostScriptProc(Graph* graphPtr, Blt_Ps ps, - Element *elemPtr) -{ - LineElement* lePtr = (LineElement *)elemPtr; - LineElementOptions* ops = (LineElementOptions*)lePtr->ops; - - // Draw fill area - if (lePtr->fillPts) { - // Create a path to use for both the polygon and its outline - Blt_Ps_Append(ps, "% start fill area\n"); - Blt_Ps_Polyline(ps, lePtr->fillPts, lePtr->nFillPts); - - // If the background fill color was specified, draw the polygon in a - // solid fashion with that color - if (lePtr->fillBgColor) { - Blt_Ps_XSetBackground(ps, lePtr->fillBgColor); - Blt_Ps_Append(ps, "gsave fill grestore\n"); - } - Blt_Ps_XSetForeground(ps, ops->fillFgColor); - if (ops->fillBg) - Blt_Ps_Append(ps, "gsave fill grestore\n"); - else - Blt_Ps_Append(ps, "gsave fill grestore\n"); - - Blt_Ps_Append(ps, "% end fill area\n"); - } - - // Draw lines (strip chart) or traces (xy graph) - if (lePtr->lines.length > 0) { - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; - link = Blt_Chain_NextLink(link)) { - LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); - LinePen* penPtr = (LinePen *)stylePtr->penPtr; - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - - if ((stylePtr->lines.length > 0) && (penOps->traceWidth > 0)) { - SetLineAttributes(ps, penPtr); - Blt_Ps_Append(ps, "% start segments\n"); - Blt_Ps_Draw2DSegments(ps, stylePtr->lines.segments, - stylePtr->lines.length); - Blt_Ps_Append(ps, "% end segments\n"); - } - } - } - else { - LinePen* penPtr = NORMALPEN(ops); - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - - if ((Blt_Chain_GetLength(lePtr->traces) > 0) && - (penOps->traceWidth > 0)) { - TracesToPostScript(ps, lePtr, penPtr); - } - } - - // Draw symbols, error bars, values - - unsigned int count =0; - for (Blt_ChainLink link = Blt_Chain_FirstLink(ops->stylePalette); link; - link = Blt_Chain_NextLink(link)) { - - LineStyle *stylePtr = (LineStyle*)Blt_Chain_GetValue(link); - LinePen* penPtr = (LinePen *)stylePtr->penPtr; - LinePenOptions* penOps = (LinePenOptions*)penPtr->ops(); - XColor* colorPtr = penOps->errorBarColor; - if (!colorPtr) - colorPtr = penOps->traceColor; - - if ((stylePtr->xeb.length > 0) && (penOps->errorBarShow & SHOW_X)) { - Blt_Ps_XSetLineAttributes(ps, colorPtr, penOps->errorBarLineWidth, - NULL, CapButt, JoinMiter); - Blt_Ps_Draw2DSegments(ps, stylePtr->xeb.segments, - stylePtr->xeb.length); - } - if ((stylePtr->yeb.length > 0) && (penOps->errorBarShow & SHOW_Y)) { - Blt_Ps_XSetLineAttributes(ps, colorPtr, penOps->errorBarLineWidth, - NULL, CapButt, JoinMiter); - Blt_Ps_Draw2DSegments(ps, stylePtr->yeb.segments, - stylePtr->yeb.length); - } - if ((stylePtr->symbolPts.length > 0) && - (penOps->symbol.type != SYMBOL_NONE)) { - SymbolsToPostScript(graphPtr, ps, penPtr, stylePtr->symbolSize, - stylePtr->symbolPts.length, - stylePtr->symbolPts.points); - } - if (penOps->valueShow != SHOW_NONE) { - ValuesToPostScript(ps, lePtr, penPtr, stylePtr->symbolPts.length, - stylePtr->symbolPts.points, - lePtr->symbolPts.map + count); - } - count += stylePtr->symbolPts.length; - } -} diff --git a/src/bltGrElemLine.h b/src/bltGrElemLine.h index 56aa92d..2238006 100644 --- a/src/bltGrElemLine.h +++ b/src/bltGrElemLine.h @@ -34,6 +34,17 @@ #include "bltGrPenLine.h" typedef enum { + PEN_INCREASING, PEN_DECREASING, PEN_BOTH_DIRECTIONS +} PenDirection; + +typedef struct { + Point2d *screenPts; + int nScreenPts; + int *styleMap; + int *map; +} MapInfo; + +typedef enum { PEN_SMOOTH_LINEAR, PEN_SMOOTH_STEP, PEN_SMOOTH_NATURAL, PEN_SMOOTH_QUADRATIC, PEN_SMOOTH_CATROM } Smoothing; @@ -45,6 +56,22 @@ typedef struct { } GraphPoints; typedef struct { + int start; + GraphPoints screenPts; +} bltTrace; + +typedef struct { + Weight weight; + LinePen* penPtr; + GraphPoints symbolPts; + GraphSegments lines; + GraphSegments xeb; + GraphSegments yeb; + int symbolSize; + int errorBarCapWidth; +} LineStyle; + +typedef struct { Element* elemPtr; const char* label; char** tags; @@ -75,38 +102,70 @@ typedef struct { int penDir; } LineElementOptions; -typedef struct { - GraphObj obj; - unsigned int flags; - int hide; - Tcl_HashEntry *hashPtr; - void* ops; - - unsigned short row; - unsigned short col; - int *activeIndices; - int nActiveIndices; - ElementProcs *procsPtr; - Tk_OptionTable optionTable; - double xRange; - double yRange; - Blt_ChainLink link; - - // Fields specific to Line Element - LinePen builtinPen; - Smoothing smooth; - XColor* fillBgColor; - GC fillGC; - Point2d *fillPts; - int nFillPts; - GraphPoints symbolPts; - GraphPoints activePts; - GraphSegments xeb; - GraphSegments yeb; - int symbolInterval; - int symbolCounter; - Blt_Chain traces; - GraphSegments lines; -} LineElement; +class LineElement : public Element { + public: + LinePen* builtinPenPtr; + Smoothing smooth_; + XColor* fillBgColor_; + GC fillGC_; + Point2d *fillPts_; + int nFillPts_; + GraphPoints symbolPts_; + GraphPoints activePts_; + GraphSegments xeb_; + GraphSegments yeb_; + GraphSegments lines_; + int symbolInterval_; + int symbolCounter_; + Blt_Chain traces_; + + protected: + int ScaleSymbol(int); + void GetScreenPoints(MapInfo*); + void ReducePoints(MapInfo*, double); + void GenerateSteps(MapInfo*); + void GenerateSpline(MapInfo*); + void GenerateParametricSpline(MapInfo*); + void MapSymbols(MapInfo*); + void MapActiveSymbols(); + void MergePens(LineStyle**); + int OutCode(Region2d*, Point2d*); + int ClipSegment(Region2d*, int, int, Point2d*, Point2d*); + void SaveTrace(int, int, MapInfo*); + void FreeTraces(); + void MapTraces(MapInfo*); + void MapFillArea(MapInfo*); + void ResetLine(); + void MapErrorBars(LineStyle**); + int ClosestTrace(); + void ClosestPoint(ClosestSearch*); + void DrawCircles(Display*, Drawable, LinePen*, int, Point2d*, int); + void DrawSquares(Display*, Drawable, LinePen*, int, Point2d*, int); + void DrawSymbols(Drawable, LinePen*, int, int, Point2d*); + void DrawTraces(Drawable, LinePen*); + void DrawValues(Drawable, LinePen*, int, Point2d*, int*); + void SetLineAttributes(Blt_Ps, LinePen*); + void TracesToPostScript(Blt_Ps, LinePen*); + void ValuesToPostScript(Blt_Ps, LinePen*, int, Point2d*, int*); + double DistanceToLine(int, int, Point2d*, Point2d*, Point2d*); + double DistanceToX(int, int, Point2d*, Point2d*, Point2d*); + double DistanceToY(int, int, Point2d*, Point2d*, Point2d*); + void SymbolsToPostScript(Blt_Ps, Pen*, int, int, Point2d*); + + public: + LineElement(Graph*, const char*, Tcl_HashEntry*); + virtual ~LineElement(); + + int configure(); + void map(); + void extents(Region2d*); + void closest(); + void drawActive(Drawable); + void drawNormal(Drawable); + void drawSymbol(Drawable, int, int, int); + void printActive(Blt_Ps); + void printNormal(Blt_Ps); + void printSymbol(Blt_Ps, double, double, int); +}; #endif diff --git a/src/bltGrElemOp.C b/src/bltGrElemOp.C index 23a6a22..4258825 100644 --- a/src/bltGrElemOp.C +++ b/src/bltGrElemOp.C @@ -33,12 +33,12 @@ extern "C" { }; #include "bltGrElem.h" +#include "bltGrElemBar.h" +#include "bltGrElemLine.h" #include "bltGrElemOp.h" // Defs -extern Element *Blt_LineElement(Graph* graphPtr); -extern Element *Blt_BarElement(Graph* graphPtr); extern int Blt_GetPenFromObj(Tcl_Interp* interp, Graph* graphPtr, Tcl_Obj *objPtr, ClassId classId, Pen **penPtrPtr); @@ -78,10 +78,10 @@ static int CreateElement(Graph* graphPtr, Tcl_Interp* interp, int objc, Element* elemPtr; switch (classId) { case CID_ELEM_BAR: - elemPtr = Blt_BarElement(graphPtr); + elemPtr = new BarElement(graphPtr,name,hPtr); break; case CID_ELEM_LINE: - elemPtr = Blt_LineElement(graphPtr); + elemPtr = new LineElement(graphPtr,name,hPtr); break; default: return TCL_ERROR; @@ -89,22 +89,9 @@ static int CreateElement(Graph* graphPtr, Tcl_Interp* interp, int objc, if (!elemPtr) return TCL_ERROR; - ElementOptions* ops = (ElementOptions*)elemPtr->ops; - elemPtr->obj.graphPtr = graphPtr; - elemPtr->obj.name = Blt_Strdup(name); - - // this is an option and will be freed via Tk_FreeConfigOptions - // By default an element's name and label are the same - ops->label = Tcl_Alloc(strlen(name)+1); - if (name) - strcpy((char*)ops->label,(char*)name); - Blt_GraphSetObjectClass(&elemPtr->obj, classId); - ops->stylePalette = Blt_Chain_Create(); - - elemPtr->hashPtr = hPtr; Tcl_SetHashValue(hPtr, elemPtr); - if ((Tk_InitOptions(graphPtr->interp, (char*)elemPtr->ops, elemPtr->optionTable, graphPtr->tkwin) != TCL_OK) || (ElementObjConfigure(interp, graphPtr, elemPtr, objc-4, objv+4) != TCL_OK)) { + if ((Tk_InitOptions(graphPtr->interp, (char*)elemPtr->ops(), elemPtr->optionTable(), graphPtr->tkwin) != TCL_OK) || (ElementObjConfigure(interp, graphPtr, elemPtr, objc-4, objv+4) != TCL_OK)) { DestroyElement(elemPtr); return TCL_ERROR; } @@ -124,21 +111,7 @@ static void DestroyElement(Element* elemPtr) if (elemPtr->link) Blt_Chain_DeleteLink(graphPtr->elements.displayList, elemPtr->link); - if (elemPtr->hashPtr) - Tcl_DeleteHashEntry(elemPtr->hashPtr); - - if (elemPtr->obj.name) - free((void*)(elemPtr->obj.name)); - - Tk_FreeConfigOptions((char*)elemPtr->ops, elemPtr->optionTable, - graphPtr->tkwin); - - (*elemPtr->procsPtr->destroyProc) (graphPtr, elemPtr); - - if (elemPtr->ops) - free(elemPtr->ops); - - free(elemPtr); + delete elemPtr; } // Configure @@ -156,7 +129,7 @@ static int CgetOp(Graph* graphPtr, Tcl_Interp* interp, return TCL_ERROR; Tcl_Obj* objPtr = Tk_GetOptionValue(interp, (char*)elemPtr, - elemPtr->optionTable, + elemPtr->optionTable(), objv[4], graphPtr->tkwin); if (objPtr == NULL) return TCL_ERROR; @@ -174,7 +147,7 @@ static int ConfigureOp(Graph* graphPtr, Tcl_Interp* interp, if (objc <= 5) { Tcl_Obj* objPtr = Tk_GetOptionInfo(graphPtr->interp, (char*)elemPtr, - elemPtr->optionTable, + elemPtr->optionTable(), (objc == 5) ? objv[4] : NULL, graphPtr->tkwin); if (objPtr == NULL) @@ -198,7 +171,7 @@ static int ElementObjConfigure(Tcl_Interp* interp, Graph* graphPtr, for (error=0; error<=1; error++) { if (!error) { - if (Tk_SetOptions(interp, (char*)elemPtr->ops, elemPtr->optionTable, + if (Tk_SetOptions(interp, (char*)elemPtr->ops(), elemPtr->optionTable(), objc, objv, graphPtr->tkwin, &savedOptions, &mask) != TCL_OK) continue; @@ -212,7 +185,7 @@ static int ElementObjConfigure(Tcl_Interp* interp, Graph* graphPtr, elemPtr->flags |= mask; elemPtr->flags |= MAP_ITEM; graphPtr->flags |= RESET_WORLD | CACHE_DIRTY; - if ((*elemPtr->procsPtr->configProc)(graphPtr, elemPtr) != TCL_OK) + if (elemPtr->configure() != TCL_OK) return TCL_ERROR; Blt_EventuallyRedrawGraph(graphPtr); @@ -269,10 +242,10 @@ static int ActivateOp(Graph* graphPtr, Tcl_Interp* interp, } } - if (elemPtr->activeIndices) - free(elemPtr->activeIndices); - elemPtr->nActiveIndices = nIndices; - elemPtr->activeIndices = indices; + if (elemPtr->activeIndices_) + free(elemPtr->activeIndices_); + elemPtr->nActiveIndices_ = nIndices; + elemPtr->activeIndices_ = indices; elemPtr->flags |= ACTIVE | ACTIVE_PENDING; Blt_EventuallyRedrawGraph(graphPtr); @@ -329,9 +302,9 @@ static int ClosestOp(Graph* graphPtr, Tcl_Interp* interp, if (Blt_GetElement(interp, graphPtr, objv[ii], &elemPtr) != TCL_OK) return TCL_ERROR; - if (elemPtr && !elemPtr->hide && + if (elemPtr && !elemPtr->hide_ && !(elemPtr->flags & (MAP_ITEM|DELETE_PENDING))) - (*elemPtr->procsPtr->closestProc) (graphPtr, elemPtr); + elemPtr->closest(); } } else { @@ -343,9 +316,9 @@ static int ClosestOp(Graph* graphPtr, Tcl_Interp* interp, for (Blt_ChainLink link=Blt_Chain_LastLink(graphPtr->elements.displayList); link != NULL; link = Blt_Chain_PrevLink(link)) { Element* elemPtr = (Element*)Blt_Chain_GetValue(link); - if (elemPtr && !elemPtr->hide && + if (elemPtr && !elemPtr->hide_ && !(elemPtr->flags & (MAP_ITEM|DELETE_PENDING))) - (*elemPtr->procsPtr->closestProc) (graphPtr, elemPtr); + elemPtr->closest(); } } @@ -385,11 +358,11 @@ static int DeactivateOp(Graph* graphPtr, Tcl_Interp* interp, if (Blt_GetElement(interp, graphPtr, objv[ii], &elemPtr) != TCL_OK) return TCL_ERROR; - if (elemPtr->activeIndices) { - free(elemPtr->activeIndices); - elemPtr->activeIndices = NULL; + if (elemPtr->activeIndices_) { + free(elemPtr->activeIndices_); + elemPtr->activeIndices_ = NULL; } - elemPtr->nActiveIndices = 0; + elemPtr->nActiveIndices_ = 0; elemPtr->flags &= ~(ACTIVE | ACTIVE_PENDING); } @@ -656,7 +629,7 @@ static void FreeElement(char* data) static int GetIndex(Tcl_Interp* interp, Element* elemPtr, Tcl_Obj *objPtr, int *indexPtr) { - ElementOptions* ops = (ElementOptions*)elemPtr->ops; + ElementOptions* ops = (ElementOptions*)elemPtr->ops(); char *string = Tcl_GetString(objPtr); if ((*string == 'e') && (strcmp("end", string) == 0)) @@ -711,7 +684,7 @@ void Blt_ConfigureElements(Graph* graphPtr) for (Blt_ChainLink link =Blt_Chain_FirstLink(graphPtr->elements.displayList); link != NULL; link = Blt_Chain_NextLink(link)) { Element* elemPtr = (Element*)Blt_Chain_GetValue(link); - (*elemPtr->procsPtr->configProc) (graphPtr, elemPtr); + elemPtr->configure(); } } @@ -727,7 +700,7 @@ void Blt_MapElements(Graph* graphPtr) continue; if ((graphPtr->flags & MAP_ALL) || (elemPtr->flags & MAP_ITEM)) { - (*elemPtr->procsPtr->mapProc) (graphPtr, elemPtr); + elemPtr->map(); elemPtr->flags &= ~MAP_ITEM; } } @@ -741,9 +714,8 @@ void Blt_DrawElements(Graph* graphPtr, Drawable drawable) for (link = Blt_Chain_LastLink(graphPtr->elements.displayList); link != NULL; link = Blt_Chain_PrevLink(link)) { Element* elemPtr = (Element*)Blt_Chain_GetValue(link); - if (!(elemPtr->flags & DELETE_PENDING) && !elemPtr->hide) { - (*elemPtr->procsPtr->drawNormalProc)(graphPtr, drawable, elemPtr); - } + if (!(elemPtr->flags & DELETE_PENDING) && !elemPtr->hide_) + elemPtr->drawNormal(drawable); } } @@ -754,11 +726,9 @@ void Blt_DrawActiveElements(Graph* graphPtr, Drawable drawable) for (link = Blt_Chain_LastLink(graphPtr->elements.displayList); link != NULL; link = Blt_Chain_PrevLink(link)) { Element* elemPtr = (Element*)Blt_Chain_GetValue(link); - if (!(elemPtr->flags & DELETE_PENDING) && - (elemPtr->flags & ACTIVE) && - !elemPtr->hide) { - (*elemPtr->procsPtr->drawActiveProc)(graphPtr, drawable, elemPtr); - } + if (!(elemPtr->flags & DELETE_PENDING) && (elemPtr->flags & ACTIVE) && + !elemPtr->hide_) + elemPtr->drawActive(drawable); } } @@ -769,12 +739,12 @@ void Blt_ElementsToPostScript(Graph* graphPtr, Blt_Ps ps) for (link = Blt_Chain_LastLink(graphPtr->elements.displayList); link != NULL; link = Blt_Chain_PrevLink(link)) { Element* elemPtr = (Element*)Blt_Chain_GetValue(link); - if (!(elemPtr->flags & DELETE_PENDING) && !elemPtr->hide) { + if (!(elemPtr->flags & DELETE_PENDING) && !elemPtr->hide_) { continue; } /* Comment the PostScript to indicate the start of the element */ Blt_Ps_Format(ps, "\n%% Element \"%s\"\n\n", elemPtr->obj.name); - (*elemPtr->procsPtr->printNormalProc) (graphPtr, ps, elemPtr); + elemPtr->printNormal(ps); } } @@ -787,10 +757,10 @@ void Blt_ActiveElementsToPostScript(Graph* graphPtr, Blt_Ps ps) Element* elemPtr = (Element*)Blt_Chain_GetValue(link); if (!(elemPtr->flags & DELETE_PENDING) && (elemPtr->flags & ACTIVE) && - !elemPtr->hide) { + !elemPtr->hide_) { Blt_Ps_Format(ps, "\n%% Active Element \"%s\"\n\n", elemPtr->obj.name); - (*elemPtr->procsPtr->printActiveProc)(graphPtr, ps, elemPtr); + elemPtr->printActive(ps); } } } diff --git a/src/bltGrPen.C b/src/bltGrPen.C index c44a496..909cbc1 100644 --- a/src/bltGrPen.C +++ b/src/bltGrPen.C @@ -29,19 +29,6 @@ #include "bltGrPen.h" -Pen::Pen() -{ - graphPtr_ =NULL; - classId_ = CID_NONE; - name_ =NULL; - optionTable_ =NULL; - ops_ =NULL; - manageOptions_ =0; - flags =0; - refCount =0; - hashPtr_ =NULL; -} - Pen::Pen(Graph* graphPtr, const char* name, Tcl_HashEntry* hPtr) { graphPtr_ = graphPtr; diff --git a/src/bltGrPenBar.C b/src/bltGrPenBar.C index 860d8cf..427bed8 100644 --- a/src/bltGrPenBar.C +++ b/src/bltGrPenBar.C @@ -74,7 +74,6 @@ static Tk_OptionSpec barPenOptionSpecs[] = { BarPen::BarPen() : Pen() { - classId_ = CID_ELEM_BAR; fillGC_ =NULL; outlineGC_ =NULL; @@ -86,7 +85,7 @@ BarPen::BarPen(Graph* graphPtr, const char* name, Tcl_HashEntry* hPtr) { classId_ = CID_ELEM_BAR; optionTable_ = Tk_CreateOptionTable(graphPtr_->interp, barPenOptionSpecs); - ops_ = (BarPenOptions*)calloc(1, sizeof(BarPenOptions)); + ops_ = calloc(1, sizeof(BarPenOptions)); manageOptions_ =1; fillGC_ =NULL; @@ -97,14 +96,19 @@ BarPen::BarPen(Graph* graphPtr, const char* name, Tcl_HashEntry* hPtr) Blt_Ts_InitStyle(ops->valueStyle); } -void BarPen::init(Graph* graphPtr, const char* penName, BarPenOptions* ops) +BarPen::BarPen(Graph* graphPtr, const char* name, void* ops) + : Pen(graphPtr, name, NULL) { - graphPtr_ = graphPtr; - name_ = dupstr(penName); + classId_ = CID_ELEM_BAR; optionTable_ = Tk_CreateOptionTable(graphPtr_->interp, barPenOptionSpecs); ops_ = ops; manageOptions_ =0; + fillGC_ =NULL; + outlineGC_ =NULL; + errorBarGC_ =NULL; + + BarPenOptions* ops = (BarPenOptions*)ops_; Blt_Ts_InitStyle(ops->valueStyle); } diff --git a/src/bltGrPenBar.h b/src/bltGrPenBar.h index 2e11fe2..5e20142 100644 --- a/src/bltGrPenBar.h +++ b/src/bltGrPenBar.h @@ -60,11 +60,10 @@ class BarPen : public Pen { GC errorBarGC_; public: - BarPen(); BarPen(Graph*, const char*, Tcl_HashEntry*); + BarPen(Graph*, const char*, void*); virtual ~BarPen(); - void init(Graph*, const char*, BarPenOptions*); int configure(); }; diff --git a/src/bltGrPenLine.C b/src/bltGrPenLine.C index 9983ac0..2f5689c 100644 --- a/src/bltGrPenLine.C +++ b/src/bltGrPenLine.C @@ -226,7 +226,7 @@ LinePen::LinePen(Graph* graphPtr, const char* name, Tcl_HashEntry* hPtr) { classId_ = CID_ELEM_LINE; optionTable_ = Tk_CreateOptionTable(graphPtr_->interp, linePenOptionSpecs); - ops_ = (LinePenOptions*)calloc(1, sizeof(LinePenOptions)); + ops_ = calloc(1, sizeof(LinePenOptions)); manageOptions_ =1; traceGC_ =NULL; @@ -239,14 +239,18 @@ LinePen::LinePen(Graph* graphPtr, const char* name, Tcl_HashEntry* hPtr) ops->symbol.type = SYMBOL_NONE; } -void LinePen::init(Graph* graphPtr, const char* penName, LinePenOptions* ops) +LinePen::LinePen(Graph* graphPtr, const char* penName, void* ops) + : Pen(graphPtr, name, NULL); { - graphPtr_ = graphPtr; - name_ = dupstr(penName); + classId_ = CID_ELEM_LINE; optionTable_ = Tk_CreateOptionTable(graphPtr_->interp, linePenOptionSpecs); ops_ = ops; manageOptions_ =0; + traceGC_ =NULL; + errorBarGC_ =NULL; + + LinePenOptions* ops = (LinePenOptions*)ops_; Blt_Ts_InitStyle(ops->valueStyle); ops->symbol.bitmap = None; ops->symbol.mask = None; diff --git a/src/bltGrPenLine.h b/src/bltGrPenLine.h index ff80664..1dbf2a5 100644 --- a/src/bltGrPenLine.h +++ b/src/bltGrPenLine.h @@ -79,11 +79,10 @@ class LinePen : public Pen { GC errorBarGC_; public: - LinePen(); LinePen(Graph*, const char*, Tcl_HashEntry*); + LinePen(Graph*, const char*, void*); virtual ~LinePen(); - void init(Graph*, const char*, LinePenOptions*); int configure(); }; diff --git a/src/bltGraph.h b/src/bltGraph.h index 4951a89..c19a8d3 100644 --- a/src/bltGraph.h +++ b/src/bltGraph.h @@ -49,7 +49,7 @@ typedef struct _Graph Graph; typedef struct _Legend Legend; typedef struct _Crosshairs Crosshairs; -typedef struct _Element Element; +class Element; typedef enum { CID_NONE, CID_AXIS_X, CID_AXIS_Y, CID_ELEM_BAR, CID_ELEM_LINE, @@ -388,11 +388,6 @@ struct _Graph { extern int Blt_PointInPolygon(Point2d *samplePtr, Point2d *screenPts, int nScreenPts); -// Elements -extern void Blt_DestroyBarSets(Graph* graphPtr); -extern void Blt_ResetBarGroups(Graph* graphPtr); -extern void Blt_InitBarSetTable(Graph* graphPtr); - // Axis extern int Blt_AxisOp(Graph* graphPtr, Tcl_Interp* interp, int objc, Tcl_Obj* const objv[]); @@ -449,7 +444,6 @@ extern Point2d Blt_Map2D(Graph* graphPtr, double x, double y, extern Graph *Blt_GetGraphFromWindowData(Tk_Window tkwin); extern int Blt_PolyRectClip(Region2d *extsPtr, Point2d *inputPts, int nInputPts, Point2d *outputPts); -extern void Blt_ComputeBarStacks(Graph* graphPtr); extern void Blt_ReconfigureGraph(Graph* graphPtr); extern void Blt_DrawGraph(Graph* graphPtr, Drawable drawable); extern void Blt_Draw2DSegments(Display *display, Drawable drawable, GC gc, |