summaryrefslogtreecommitdiffstats
path: root/tkblt/generic/tkbltGrElem.C
diff options
context:
space:
mode:
Diffstat (limited to 'tkblt/generic/tkbltGrElem.C')
-rw-r--r--tkblt/generic/tkbltGrElem.C284
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);
+ }
+ }
+}
+