/* * 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 #include #include #include #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 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; iinValues(); 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; iistylePalette); 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); } } }