diff options
Diffstat (limited to 'tkblt/generic/tkbltGrElem.C')
-rw-r--r-- | tkblt/generic/tkbltGrElem.C | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/tkblt/generic/tkbltGrElem.C b/tkblt/generic/tkbltGrElem.C new file mode 100644 index 0000000..faf1b72 --- /dev/null +++ b/tkblt/generic/tkbltGrElem.C @@ -0,0 +1,284 @@ +/* + * Smithsonian Astrophysical Observatory, Cambridge, MA, USA + * This code has been modified under the terms listed below and is made + * available under the same terms. + */ + +/* + * Copyright 1993-2004 George A Howlett. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <float.h> +#include <stdlib.h> +#include <string.h> + +#include <cmath> + +#include "tkbltGraph.h" +#include "tkbltGrBind.h" +#include "tkbltGrElem.h" +#include "tkbltGrPen.h" +#include "tkbltInt.h" + +using namespace Blt; + +// Class ElemValues + +ElemValues::ElemValues() +{ + values_ =NULL; + nValues_ =0; + min_ =0; + max_ =0; +} + +ElemValues::~ElemValues() +{ + delete [] values_; +} + +void ElemValues::reset() +{ + delete [] values_; + values_ =NULL; + nValues_ =0; + min_ =0; + max_ =0; +} + +ElemValuesSource::ElemValuesSource(int nn) : ElemValues() +{ + nValues_ = nn; + values_ = new double[nn]; +} + +ElemValuesSource::ElemValuesSource(int nn, double* vv) : ElemValues() +{ + nValues_ = nn; + values_ = vv; +} + +ElemValuesSource::~ElemValuesSource() +{ +} + +void ElemValuesSource::findRange() +{ + if (nValues_<1 || !values_) + return; + + min_ = DBL_MAX; + max_ = -DBL_MAX; + for (int ii=0; ii<nValues_; ii++) { + if (isfinite(values_[ii])) { + if (values_[ii] < min_) + min_ = values_[ii]; + if (values_[ii] > max_) + max_ = values_[ii]; + } + } +} + +ElemValuesVector::ElemValuesVector(Element* ptr, const char* vecName) + : ElemValues() +{ + elemPtr_ = ptr; + Graph* graphPtr = elemPtr_->graphPtr_; + source_ = Blt_AllocVectorId(graphPtr->interp_, vecName); +} + +ElemValuesVector::~ElemValuesVector() +{ + freeSource(); +} + +int ElemValuesVector::getVector() +{ + Graph* graphPtr = elemPtr_->graphPtr_; + + Blt_Vector *vecPtr; + if (Blt_GetVectorById(graphPtr->interp_, source_, &vecPtr) != TCL_OK) + return TCL_ERROR; + + if (fetchValues(vecPtr) != TCL_OK) { + freeSource(); + return TCL_ERROR; + } + + Blt_SetVectorChangedProc(source_, VectorChangedProc, this); + return TCL_OK; +} + +int ElemValuesVector::fetchValues(Blt_Vector* vector) +{ + Graph* graphPtr = elemPtr_->graphPtr_; + + delete [] values_; + values_ = NULL; + nValues_ = 0; + min_ =0; + max_ =0; + + int ss = Blt_VecLength(vector); + if (!ss) + return TCL_OK; + + double* array = new double[ss]; + if (!array) { + Tcl_AppendResult(graphPtr->interp_, "can't allocate new vector", NULL); + return TCL_ERROR; + } + + memcpy(array, Blt_VecData(vector), ss*sizeof(double)); + values_ = array; + nValues_ = Blt_VecLength(vector); + min_ = Blt_VecMin(vector); + max_ = Blt_VecMax(vector); + + return TCL_OK; +} + +void ElemValuesVector::freeSource() +{ + if (source_) { + Blt_SetVectorChangedProc(source_, NULL, NULL); + Blt_FreeVectorId(source_); + source_ = NULL; + } +} + +// Class Element + +Element::Element(Graph* graphPtr, const char* name, Tcl_HashEntry* hPtr) +{ + graphPtr_ = graphPtr; + name_ = dupstr(name); + optionTable_ =NULL; + ops_ =NULL; + hashPtr_ = hPtr; + + row_ =0; + col_ =0; + activeIndices_ =NULL; + nActiveIndices_ =0; + xRange_ =0; + yRange_ =0; + active_ =0; + labelActive_ =0; + + link =NULL; +} + +Element::~Element() +{ + graphPtr_->bindTable_->deleteBindings(this); + + if (link) + graphPtr_->elements_.displayList->deleteLink(link); + + if (hashPtr_) + Tcl_DeleteHashEntry(hashPtr_); + + delete [] name_; + + delete [] activeIndices_; + + Tk_FreeConfigOptions((char*)ops_, optionTable_, graphPtr_->tkwin_); + free(ops_); +} + +double Element::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); + double* w = ops->w ? ops->w->values_ : NULL; + ChainLink* link = Chain_FirstLink(ops->stylePalette); + PenStyle* stylePtr = (PenStyle*)Chain_GetValue(link); + + // Create a style mapping array (data point index to style), + // initialized to the default style. + PenStyle** dataToStyle = new PenStyle*[nPoints]; + for (int ii=0; ii<nPoints; ii++) + dataToStyle[ii] = stylePtr; + + for (int ii=0; ii<nWeights; ii++) { + for (link=Chain_LastLink(ops->stylePalette); link; + link=Chain_PrevLink(link)) { + stylePtr = (PenStyle*)Chain_GetValue(link); + + if (stylePtr->weight.range > 0.0) { + double norm = (w[ii] - stylePtr->weight.min) / stylePtr->weight.range; + if (((norm - 1.0) <= DBL_EPSILON) && + (((1.0 - norm) - 1.0) <= DBL_EPSILON)) { + dataToStyle[ii] = stylePtr; + break; + } + } + } + } + + return dataToStyle; +} + +void Element::freeStylePalette(Chain* stylePalette) +{ + // Skip the first slot. It contains the built-in "normal" pen of the element + ChainLink* link = Chain_FirstLink(stylePalette); + if (link) { + ChainLink* next; + for (link=Chain_NextLink(link); link; link=next) { + next = Chain_NextLink(link); + PenStyle *stylePtr = (PenStyle*)Chain_GetValue(link); + Pen* penPtr = stylePtr->penPtr; + if (penPtr) { + penPtr->refCount_--; + if (penPtr->refCount_ == 0) + delete penPtr; + } + stylePalette->deleteLink(link); + } + } +} + |