Skip to content

Commit

Permalink
Merge pull request ngageoint#646 in WV/opensphere from ~GIBSONC/opens…
Browse files Browse the repository at this point in the history
…phere:THIN-12613 to master

* commit '2c4f331a978183f1b6a3ced72d98a76e1863c454':
  test(datebinmethodtest): remove value that is now supported
  feat(sourcehistogram): add secondary bin method capability to source histogram and bin methods
  • Loading branch information
welchyd committed Mar 9, 2019
2 parents 9ee6abe + 2c4f331 commit c60771b
Show file tree
Hide file tree
Showing 13 changed files with 753 additions and 88 deletions.
26 changes: 19 additions & 7 deletions src/os/data/histo/colorbin.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ goog.require('os.style');


/**
* Histogram bin that tracks the colors of features in the bin.
* Histogram bin that tracks the colors of items in the bin.
* @param {string} baseColor The base color of the layer represented by this bin
* @extends {os.histo.Bin<!ol.Feature>}
* @extends {os.histo.Bin<T>}
* @template T
* @constructor
*/
os.data.histo.ColorBin = function(baseColor) {
Expand All @@ -25,7 +26,7 @@ os.data.histo.ColorBin = function(baseColor) {
this.baseColor_ = os.color.toHexString(baseColor);

/**
* Number of features in the bin with a given color.
* Number of items in the bin with a given color.
* @type {Object<string, number>}
* @private
*/
Expand Down Expand Up @@ -89,15 +90,26 @@ os.data.histo.ColorBin.prototype.removeItem = function(item) {

/**
* Get the color of an item.
* @param {!ol.Feature} item The item.
* @param {T} item The item.
* @return {string|undefined} The item color, or null if no custom color is defined.
*
* @suppress {accessControls} To allow direct access to feature metadata.
*/
os.data.histo.ColorBin.prototype.getItemColor = function(item) {
// check if the feature has a color override
var color = /** @type {string|undefined} */ (os.feature.getColor(item));
return color || undefined;
// check for a color override
if (os.instanceOf(item, ol.Feature.NAME)) {
return /** @type {string|undefined} */ (os.feature.getColor(/** @type {!ol.Feature} */ (item)));
} else {
item = /** @type {Object<string, *>} */ (item);
if (item.getColor != null) {
return /** @type {string|undefined} */ (item.getColor());
} else if (item['color'] != null) {
return /** @type {string|undefined} */ (item['color']);
} else if (item.color != null) {
return /** @type {string|undefined} */ (item.color);
}
}
return undefined;
};


Expand Down
172 changes: 166 additions & 6 deletions src/os/data/histo/sourcehistogram.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ os.data.histo.SourceHistogram = function(source, opt_parent) {
*/
this.id_ = os.data.histo.SourceHistogram.ID + os.data.histo.SourceHistogram.nextId++;

/**
* Key for xf dimension with multi key string
* @type {string}
* @private
*/
this.multiId_ = this.id_ + 'multi';

/**
* @type {goog.log.Logger}
* @protected
Expand All @@ -58,6 +65,28 @@ os.data.histo.SourceHistogram = function(source, opt_parent) {
*/
this.binMethod = null;

/**
* Bin method that does not get it's own dimension on the dataModel, rather it creates a dimension pivoted
* from this.binMethod
* @type {?os.histo.IBinMethod<ol.Feature>}
* @protected
*/
this.secondaryBinMethod = null;

/**
* The accessor function created from smashing together the primary and secondary bin methods
* @type {null|function(ol.Feature):string}
* @protected
*/
this.combinedAccessor = null;

/**
* The key method created from smashing together the primary and secondary key functions
* @type {null|function(string):string}
* @protected
*/
this.combinedKeyMethod = null;

/**
* The source for the histogram
* @type {os.source.Vector}
Expand Down Expand Up @@ -100,6 +129,13 @@ os.data.histo.SourceHistogram = function(source, opt_parent) {
*/
this.binRanges_ = false;

/**
* Whether the filters on the timemodel should be ignored when grouping data
* @type {boolean}
* @private
*/
this.forceAllData_ = false;

/**
* The sorting function
* @type {?os.histo.bin.SortFn}
Expand Down Expand Up @@ -187,8 +223,12 @@ os.data.histo.SourceHistogram.prototype.disposeInternal = function() {
this.updateDelay_ = null;

this.setBinMethod(null);
this.setSecondaryBinMethod(null);

this.results.length = 0;

this.timeModel_.removeDimension(this.id_);
this.timeModel_.removeDimension(this.multiId_);
};


Expand Down Expand Up @@ -241,6 +281,15 @@ os.data.histo.SourceHistogram.prototype.getId = function() {
};


/**
* Get the 2D histogram id.
* @return {string}
*/
os.data.histo.SourceHistogram.prototype.getMultiId = function() {
return this.multiId_;
};


/**
* Get the cascaded values for this histogram.
* @return {Array<*>}
Expand Down Expand Up @@ -311,6 +360,15 @@ os.data.histo.SourceHistogram.prototype.getBinMethod = function() {
};


/**
* Get the secondary bin method.
* @return {os.histo.IBinMethod<ol.Feature>}
*/
os.data.histo.SourceHistogram.prototype.getSecondaryBinMethod = function() {
return this.secondaryBinMethod;
};


/**
* Sets the bin method.
* @param {os.histo.IBinMethod<ol.Feature>} method
Expand All @@ -322,7 +380,9 @@ os.data.histo.SourceHistogram.prototype.setBinMethod = function(method) {
this.binMethod = os.histo.cloneMethod(method);

if (this.binMethod) {
this.binMethod.setValueFunction(os.feature.getField);
if (this.binMethod.getValueFunction() == null) {
this.binMethod.setValueFunction(os.feature.getField);
}
this.binRanges_ = this.binMethod.getArrayKeys() || false;
}

Expand All @@ -332,6 +392,53 @@ os.data.histo.SourceHistogram.prototype.setBinMethod = function(method) {
};


/**
* Sets the secondary bin method.
* @param {os.histo.IBinMethod<ol.Feature>} method
*
* @export Prevent the compiler from moving the function off the prototype.
*/
os.data.histo.SourceHistogram.prototype.setSecondaryBinMethod = function(method) {
// clone to the local context to prevent leaks
this.secondaryBinMethod = os.histo.cloneMethod(method);

if (this.secondaryBinMethod) {
if (this.secondaryBinMethod.getValueFunction() == null) {
this.secondaryBinMethod.setValueFunction(os.feature.getField);
}

/**
* Do the binning for each dimension to create a xf key that represents the bins that would contain the item
* @param {ol.Feature} item
* @return {string}
*/
this.combinedAccessor = function(item) {
return this.binMethod.getBinKey(this.binMethod.getValue(item)).toString() + os.data.xf.DataModel.SEPARATOR +
this.secondaryBinMethod.getBinKey(this.secondaryBinMethod.getValue(item)).toString();
};

/**
* Warning: returning anything but the xf key may result in unexpected binning as the order in xf for the accessor
* and this key grouping method must be the same
* @param {string} key
* @return {string}
*/
this.combinedKeyMethod = function(key) {
return key;
};
} else {
// no method provided; remove the current one
this.secondaryBinMethod = null;
this.combinedAccessor = null;
this.combinedKeyMethod = null;
}

this.reindex();
this.update();
this.dispatchEvent(os.data.histo.HistoEventType.BIN_CHANGE);
};


/**
* Re-index data in the time model.
* @protected
Expand All @@ -347,6 +454,12 @@ os.data.histo.SourceHistogram.prototype.reindex = function() {
os.histo.DateRangeBinType[this.binMethod.getDateBinType()] : false;
isArray = this.binRanges_ ? isArray : false;
this.timeModel_.addDimension(this.id_, valueFn, isArray);

if (this.secondaryBinMethod) {
this.timeModel_.addDimension(this.multiId_, this.combinedAccessor.bind(this), isArray);
} else {
this.timeModel_.removeDimension(this.multiId_);
}
}
}
};
Expand Down Expand Up @@ -414,7 +527,6 @@ os.data.histo.SourceHistogram.prototype.getResults = function() {

/**
* Update results from crossfilter.
* @protected
*/
os.data.histo.SourceHistogram.prototype.updateResults = function() {
var results = [];
Expand All @@ -437,16 +549,33 @@ os.data.histo.SourceHistogram.prototype.updateResults = function() {
}
}

results = /** @type {!Array<!os.histo.Result<!ol.Feature>>} */ (this.timeModel_.groupData(this.id_,
this.binMethod.getBinKey.bind(this.binMethod), this.reduceAdd.bind(this),
this.reduceRemove.bind(this), this.reduceInit.bind(this)));
// clear the filters to get all of the data
if (this.forceAllData_ == true) {
this.timeModel_.clearAllFilters();
}

if (this.secondaryBinMethod) {
results = /** @type {!Array<!os.histo.Result<!ol.Feature>>} */ (this.timeModel_.groupData(this.multiId_,
this.combinedKeyMethod.bind(this), this.reduceAdd.bind(this),
this.reduceRemove.bind(this), this.reduceInit.bind(this)));
} else {
results = /** @type {!Array<!os.histo.Result<!ol.Feature>>} */ (this.timeModel_.groupData(this.id_,
this.binMethod.getBinKey.bind(this.binMethod), this.reduceAdd.bind(this),
this.reduceRemove.bind(this), this.reduceInit.bind(this)));
}

// reapply the time ranges
if (this.source && this.forceAllData_ == true) {
this.source.getFilteredFeatures();
}

if (filters) {
for (var id in filters) {
this.timeModel_.filterDimension(id, undefined);
}
}


results = /** @type {!Array<!os.data.histo.ColorBin>} */ (results.map(this.map, this).filter(function(item) {
return item != undefined;
}));
Expand Down Expand Up @@ -476,7 +605,13 @@ os.data.histo.SourceHistogram.prototype.map = function(item, i, arr) {
}

bin.setKey(item.key);
bin.setLabel(this.binMethod.getLabelForKey(item.key));

if (this.secondaryBinMethod) {
bin.setLabel(this.binMethod.getLabelForKey(item.key, false, true) + os.data.xf.DataModel.SEPARATOR +
this.secondaryBinMethod.getLabelForKey(item.key, true, true));
} else {
bin.setLabel(this.binMethod.getLabelForKey(item.key));
}

return bin;
};
Expand Down Expand Up @@ -629,6 +764,15 @@ os.data.histo.SourceHistogram.prototype.onFeatureColor_ = function(event) {
};


/**
* @param {string|number} id The feature id
* @return {os.data.histo.ColorBin}
*/
os.data.histo.SourceHistogram.prototype.getBinByFeatureId = function(id) {
return this.featureBins_[id] || null;
};


/**
* @param {boolean} value The value
*/
Expand All @@ -651,3 +795,19 @@ os.data.histo.SourceHistogram.prototype.setBinRanges = function(value) {
os.data.histo.SourceHistogram.prototype.getBinRanges = function() {
return this.binRanges_;
};


/**
* @param {boolean} value The value
*/
os.data.histo.SourceHistogram.prototype.setForceAllData = function(value) {
this.forceAllData_ = value;
};


/**
* @return {boolean} the value
*/
os.data.histo.SourceHistogram.prototype.getForceAllData = function() {
return this.forceAllData_;
};
8 changes: 8 additions & 0 deletions src/os/data/xf/datamodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ os.data.xf.DataModel = function() {
goog.inherits(os.data.xf.DataModel, goog.events.EventTarget);


/**
* Separator for multidimensional grouping
* @type {string}
* @const
*/
os.data.xf.DataModel.SEPARATOR = '$%';


/**
* Logger
* @type {goog.log.Logger}
Expand Down
Loading

0 comments on commit c60771b

Please sign in to comment.