-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a pixelmap feature #637
Conversation
This takes an image where the color values are treated as indices into the data data. This is used to generate a new color for each index. The resultant image is rendered as a quad. The feature is available of the d3, canvas, and vgl renderers.
Only gl features honored visibility, and then only if they did not consist of secondary features. Visibility now works on all renderers and a concept of dependentFeatures has been added to group visibility for certain features. Some features still probably don't support visibility properly (such as the graphFeature), but that should be left for a different fix.
The features() function replaced features but without properly ensure dropped features were removed or new features were added.
This returns the maximum value from the pixelmap index (not the number of distinct indices). ((maxIndex() + 1) is the useful length of the data array. Also, don't reload the index values from the pixelmap if it isn't necessary. When only the data updates, this saves drawing the pixelmap to a canvas.
Significantly increase the speed by caching more and updating less. Specifically, the working canvas is maintained between updates, and only changed portions are updated. canvas.toBlob is used in preference to canvas.toDataURL if it is available. maxIndex is cached. Added a fallback for boxSearch to the feature class to suppress some console warnings.
Use canvas properties for faster drawing of the final image. Compute only the extent of the changed area and only update that extent. This computes colors in one pass and updated pixels in a second pass rather than computing them in the same loop. The first render is probably very slightly slower.
Some changes were made to the quad feature and other details in PRs that haven't been merged in but affect the new pixelmap feature. This adjusts for them (mainly using the extra parameter on found points).
Also, handle more css color specifications. Currently, nothing takes advantage of a color which has an alpha value (though the pixelmap soon will). It would be nice to be able to use that in addition to opacity styles. Before, we handled colors of the form rgb object, #rrggbb, #rgb, and css color names. This adds parsing of #rrggbbaa, #rgba, rgb(), rgba(), hsl(), hsla(), and 'transparent', conforming that parsing to the css working group's current draft standard (there are other color formats in that draft that are not implemented). It also adds one additional css color name, as per that draft.
Refactored how image elements are used for the pixelmap so that the pixelmap becomes a deferred object. Fixed a petty issue with setting an image's crossOrigin property even when it was a data url.
Current coverage is 86.86% (diff: 100%)@@ master #637 diff @@
==========================================
Files 85 87 +2
Lines 8340 8544 +204
Methods 0 0
Messages 0 0
Branches 0 0
==========================================
+ Hits 7218 7422 +204
Misses 1122 1122
Partials 0 0
|
@aashish24 All dependent PRs have been merged in. This is ready for review. |
Awesome feature 👏 👏 just has some minor things in the review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had few comments / suggestions. I think mapColor could be color or colorMap for simplicity
} | ||
pixelmapFeature.call(this, arg); | ||
|
||
var object = require('./object'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious: why you had to do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In our various renderers, we have renderer-specific changes to objects, mostly to make a renderer-specific draw method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, thanks.
|
||
//////////////////////////////////////////////////////////////////////////// | ||
/** | ||
* Get the maximum index value from the pixelmap. This is a value present in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: in could be in the next line since its probably on column 79-80
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'in' ends at column 79. Do you really want to change to less than 80 line lengths?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its fine then. on web-page it looks as if it was outside that's why I added probably
* @returns {geo.pixelmap} | ||
*/ | ||
//////////////////////////////////////////////////////////////////////////// | ||
this.mapColor = function (val) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@manthey I am wondering why don't we just call it color like other features? since it is primarily a color transfer function? Also, I would think this should be a style element.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah. I see later that it is a style element so why we need this method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In many features, we have certain styles also accessible by functions (position often is, even if we store it in style as well). This allows for an easy side effect, such as only marking this as changed if it is actually different.
The problem with this approach in general is that we have different behaviors if these properties are set via style versus the special function -- for instance, style('position', <value>)
won't update the dataTime and will always updated the modified time, even if the passed value is the same as the previous one. We might want to refactor the feature style method so that it is easier to have convenience functions and the behavior is identical regardless of whether the convenience function or style is used. However, that should be a general change, and not in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only feature that has a plain color
style is the solid-color quad feature. All other features have styles name fillColor
, strokeColor
, and probably others. My logic was to name it with a prefix to be clear what it was (but perhaps it doesn't help). We can rename this to color
if you think that is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
heatmap uses color
. color could be static or a transfer function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my preference would be slightly more towardscolor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with this approach in general is that we have different behaviors if these properties are set via style versus the special function -- for instance, style('position', ) won't update the dataTime and will always updated the modified time, even if the passed value is the same as the previous one. We might want to refactor the feature style method so that it is easier to have convenience functions and the behavior is identical regardless of whether the convenience function or style is used. However, that should be a general change, and not in this PR.
Sure, let's keep this method and then we can revisit it once we refactor style function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
color would be better I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I'll switch it to color
.
m_srcImage.crossOrigin = this.style.get('crossDomain')() || 'anonymous'; | ||
} | ||
} | ||
m_srcImage.onload = function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this code is only needed for else if and else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The onload function is used on both a newly created Image and on an existing Image that isn't complete. It is within the else if
clause on line 180.
this._preparePixelmap = function () { | ||
var i, idx, pixelData; | ||
|
||
if (!m_srcImage || !m_srcImage.complete || !m_srcImage.naturalWidth || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this is a repeating code, may be in this or next PR we could write a function instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll make a utility function.
m_info.imageData, 0, 0, 0, Math.floor(updateFirst / m_info.width), | ||
m_info.width, Math.ceil((updateLast + 1) / m_info.width)); | ||
|
||
/* If we haven't made a quad feature, make one now. The quad feature needs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick (can be done in another PR): Spacing between . (dot) and the.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm of the camp that there should be more spaces between sentences then between words. It is a topic of much bike-shedding (https://en.wikipedia.org/wiki/Sentence_spacing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am fine with that if we are consistent, may be we can change them at some point but i think right now we use single space. Not a roadblock for this PR though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A quick grep shows 400+ uses of two spaces and 50 uses of 1 space. I think this should be left to the discretion of whomever writes comments, much like oxford commas, tight or loose punctuation, and other optional grammar rules.
Add a utility function to determine if an object is an HTML image element that is fully loaded.
sure, as I referred earlier, I am not in favor of making it part for this PR. |
@brianhelba We've renamed the |
thanks @manthey. LGTM 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
Nice. Talked to @jbeezley and sounds like we are ready for another point release. |
This takes an image where the color values are treated as indices into the data data. This is used to generate a new color for each index. The resultant image is rendered as a quad. The feature is available in the canvas renderer.
The pixelmap image can be specified as a url or given as a Image element. The pixelmap feature will be a deferred jquery object if the image needs to be loaded.
This depends on PRs #633, #634, #635, and #636.
I've left the history of this branch as it has code that shows how this could be extended to non-canvas renderers (though it is slower).
The example uses a pixelmap of the United States and some political data that is probably already out of date.