diff options
author | Charles Nicholson <nicholsonc@google.com> | 2016-11-15 11:17:43 -0800 |
---|---|---|
committer | TensorFlower Gardener <gardener@tensorflow.org> | 2016-11-15 11:25:49 -0800 |
commit | aaa1f1a35ad2d584100d5524a547d8f92be755c4 (patch) | |
tree | 6552ed093951428fb1755956e18a1a972a021910 | |
parent | ff01301128a23bbe1c03d9f8c677f5f076989016 (diff) |
RGB Uint8 arrays for canvas label fill and stroke styles. Allows us to change
the label coloring for selected / hover / neighbor points, coming soon.
Change: 139223883
3 files changed, 64 insertions, 80 deletions
diff --git a/tensorflow/tensorboard/components/vz_projector/projectorScatterPlotAdapter.ts b/tensorflow/tensorboard/components/vz_projector/projectorScatterPlotAdapter.ts index 881be3989a..2d8c790747 100644 --- a/tensorflow/tensorboard/components/vz_projector/projectorScatterPlotAdapter.ts +++ b/tensorflow/tensorboard/components/vz_projector/projectorScatterPlotAdapter.ts @@ -20,8 +20,8 @@ import {LabelRenderParams} from './renderContext'; const LABEL_FONT_SIZE = 10; const LABEL_SCALE_DEFAULT = 1.0; const LABEL_SCALE_LARGE = 2; -const LABEL_FILL_COLOR = 0x000000; -const LABEL_STROKE_COLOR = 0xFFFFFF; +const LABEL_FILL_COLOR = '#000000'; +const LABEL_STROKE_COLOR = '#FFFFFF'; const POINT_COLOR_UNSELECTED = 0xE3E3E3; const POINT_COLOR_NO_SELECTION = 0x7575D9; @@ -104,6 +104,14 @@ export class ProjectorScatterPlotAdapter { return positions; } + private packRgbIntoUint8Array( + rgbArray: Uint8Array, labelIndex: number, r: number, g: number, + b: number) { + rgbArray[labelIndex * 3] = r; + rgbArray[labelIndex * 3 + 1] = g; + rgbArray[labelIndex * 3 + 2] = b; + } + generateVisibleLabelRenderParams( ds: DataSet, selectedPointIndices: number[], neighborsOfFirstPoint: NearestEntry[], @@ -118,6 +126,11 @@ export class ProjectorScatterPlotAdapter { const visibleLabels = new Uint32Array(n); const scale = new Float32Array(n); const opacityFlags = new Int8Array(n); + const fillColors = new Uint8Array(n * 3); + const strokeColors = new Uint8Array(n * 3); + + const fillRgb = d3.rgb(LABEL_FILL_COLOR); + const strokeRgb = d3.rgb(LABEL_STROKE_COLOR); scale.fill(LABEL_SCALE_DEFAULT); opacityFlags.fill(1); @@ -128,6 +141,10 @@ export class ProjectorScatterPlotAdapter { visibleLabels[dst] = hoverPointIndex; scale[dst] = LABEL_SCALE_LARGE; opacityFlags[dst] = 0; + this.packRgbIntoUint8Array( + fillColors, dst, fillRgb.r, fillRgb.g, fillRgb.b); + this.packRgbIntoUint8Array( + strokeColors, dst, strokeRgb.r, strokeRgb.g, strokeRgb.b); ++dst; } @@ -138,6 +155,10 @@ export class ProjectorScatterPlotAdapter { visibleLabels[dst] = selectedPointIndices[i]; scale[dst] = LABEL_SCALE_LARGE; opacityFlags[dst] = (n === 1) ? 0 : 1; + this.packRgbIntoUint8Array( + fillColors, dst, fillRgb.r, fillRgb.g, fillRgb.b); + this.packRgbIntoUint8Array( + strokeColors, dst, strokeRgb.r, strokeRgb.g, strokeRgb.b); ++dst; } } @@ -146,13 +167,18 @@ export class ProjectorScatterPlotAdapter { { const n = neighborsOfFirstPoint.length; for (let i = 0; i < n; ++i) { - visibleLabels[dst++] = neighborsOfFirstPoint[i].index; + visibleLabels[dst] = neighborsOfFirstPoint[i].index; + this.packRgbIntoUint8Array( + fillColors, dst, fillRgb.r, fillRgb.g, fillRgb.b); + this.packRgbIntoUint8Array( + strokeColors, dst, strokeRgb.r, strokeRgb.g, strokeRgb.b); + ++dst; } } return new LabelRenderParams( - visibleLabels, scale, opacityFlags, LABEL_FONT_SIZE, LABEL_FILL_COLOR, - LABEL_STROKE_COLOR); + visibleLabels, scale, opacityFlags, LABEL_FONT_SIZE, fillColors, + strokeColors); } generatePointScaleFactorArray( diff --git a/tensorflow/tensorboard/components/vz_projector/renderContext.ts b/tensorflow/tensorboard/components/vz_projector/renderContext.ts index 115965a6ed..544f23538c 100644 --- a/tensorflow/tensorboard/components/vz_projector/renderContext.ts +++ b/tensorflow/tensorboard/components/vz_projector/renderContext.ts @@ -18,24 +18,10 @@ limitations under the License. * rendered next to them. */ export class LabelRenderParams { - pointIndices: Float32Array; - scaleFactors: Float32Array; - useSceneOpacityFlags: Int8Array; // booleans - defaultFontSize: number; - fillColor: number; - strokeColor: number; - constructor( - pointIndices: Float32Array, scaleFactors: Float32Array, - useSceneOpacityFlags: Int8Array, defaultFontSize: number, - fillColor: number, strokeColor: number) { - this.pointIndices = pointIndices; - this.scaleFactors = scaleFactors; - this.useSceneOpacityFlags = useSceneOpacityFlags; - this.defaultFontSize = defaultFontSize; - this.fillColor = fillColor; - this.strokeColor = strokeColor; - } + public pointIndices: Float32Array, public scaleFactors: Float32Array, + public useSceneOpacityFlags: Int8Array, public defaultFontSize: number, + public fillColors: Uint8Array, public strokeColors: Uint8Array) {} } /** Details about the camera projection being used to render the scene. */ @@ -53,44 +39,14 @@ export enum CameraType { * only when they change. */ export class RenderContext { - camera: THREE.Camera; - cameraType: CameraType; - cameraTarget: THREE.Vector3; - screenWidth: number; - screenHeight: number; - nearestCameraSpacePointZ: number; - farthestCameraSpacePointZ: number; - backgroundColor: number; - pointColors: Float32Array; - pointScaleFactors: Float32Array; - labelAccessor: (index: number) => string; - labels: LabelRenderParams; - traceColors: {[trace: number]: Float32Array}; - traceOpacities: Float32Array; - traceWidths: Float32Array; - constructor( - camera: THREE.Camera, cameraType: CameraType, cameraTarget: THREE.Vector3, - screenWidth: number, screenHeight: number, - nearestCameraSpacePointZ: number, farthestCameraSpacePointZ: number, - backgroundColor: number, pointColors: Float32Array, - pointScaleFactors: Float32Array, labelAccessor: (index: number) => string, - labels: LabelRenderParams, traceColors: {[trace: number]: Float32Array}, - traceOpacities: Float32Array, traceWidths: Float32Array) { - this.camera = camera; - this.cameraType = cameraType; - this.cameraTarget = cameraTarget; - this.screenWidth = screenWidth; - this.screenHeight = screenHeight; - this.nearestCameraSpacePointZ = nearestCameraSpacePointZ; - this.farthestCameraSpacePointZ = farthestCameraSpacePointZ; - this.backgroundColor = backgroundColor; - this.pointColors = pointColors; - this.pointScaleFactors = pointScaleFactors; - this.labelAccessor = labelAccessor; - this.labels = labels; - this.traceColors = traceColors; - this.traceOpacities = traceOpacities; - this.traceWidths = traceWidths; - } + public camera: THREE.Camera, public cameraType: CameraType, + public cameraTarget: THREE.Vector3, public screenWidth: number, + public screenHeight: number, public nearestCameraSpacePointZ: number, + public farthestCameraSpacePointZ: number, public backgroundColor: number, + public pointColors: Float32Array, public pointScaleFactors: Float32Array, + public labelAccessor: (index: number) => string, + public labels: LabelRenderParams, + public traceColors: {[trace: number]: Float32Array}, + public traceOpacities: Float32Array, public traceWidths: Float32Array) {} } diff --git a/tensorflow/tensorboard/components/vz_projector/scatterPlotVisualizerCanvasLabels.ts b/tensorflow/tensorboard/components/vz_projector/scatterPlotVisualizerCanvasLabels.ts index 58d52f39e6..e6439d6849 100644 --- a/tensorflow/tensorboard/components/vz_projector/scatterPlotVisualizerCanvasLabels.ts +++ b/tensorflow/tensorboard/components/vz_projector/scatterPlotVisualizerCanvasLabels.ts @@ -53,17 +53,9 @@ export class ScatterPlotVisualizerCanvasLabels implements return; } + const lrc = rc.labels; const sceneIs3D: boolean = (rc.cameraType === CameraType.Perspective); - let strokeStylePrefix: string; - let fillStylePrefix: string; - { - const ls = new THREE.Color(rc.labels.strokeColor).multiplyScalar(255); - const lc = new THREE.Color(rc.labels.fillColor).multiplyScalar(255); - strokeStylePrefix = 'rgba(' + ls.r + ',' + ls.g + ',' + ls.b + ','; - fillStylePrefix = 'rgba(' + lc.r + ',' + lc.g + ',' + lc.b + ','; - } - const labelHeight = parseInt(this.gc.font, 10); const dpr = window.devicePixelRatio; @@ -75,9 +67,11 @@ export class ScatterPlotVisualizerCanvasLabels implements grid = new CollisionGrid(bb, pixw / 25, pixh / 50); } - let opacityMap = d3.scale.pow().exponent(Math.E) - .domain([rc.farthestCameraSpacePointZ, rc.nearestCameraSpacePointZ]) - .range([0.1, 1]); + let opacityMap = + d3.scale.pow() + .exponent(Math.E) + .domain([rc.farthestCameraSpacePointZ, rc.nearestCameraSpacePointZ]) + .range([0.1, 1]); const camPos = rc.camera.position; const camToTarget = camPos.clone().sub(rc.cameraTarget); @@ -91,9 +85,9 @@ export class ScatterPlotVisualizerCanvasLabels implements // Shift the label to the right of the point circle. const xShift = 4; - const n = Math.min(MAX_LABELS_ON_SCREEN, rc.labels.pointIndices.length); + const n = Math.min(MAX_LABELS_ON_SCREEN, lrc.pointIndices.length); for (let i = 0; i < n; ++i) { - const index = rc.labels.pointIndices[i]; + const index = lrc.pointIndices[i]; const point = util.vector3FromPackedArray(this.worldSpacePointPositions, index); @@ -119,19 +113,22 @@ export class ScatterPlotVisualizerCanvasLabels implements if (grid.insert(textBoundingBox, true)) { const text = rc.labelAccessor(index); - const fontSize = - rc.labels.defaultFontSize * rc.labels.scaleFactors[i] * dpr; + const fontSize = lrc.defaultFontSize * lrc.scaleFactors[i] * dpr; this.gc.font = fontSize + 'px roboto'; // Now, check with properly computed width. textBoundingBox.hiX += this.gc.measureText(text).width - 1; if (grid.insert(textBoundingBox)) { let opacity = 1; - if (sceneIs3D && (rc.labels.useSceneOpacityFlags[i] === 1)) { + if (sceneIs3D && (lrc.useSceneOpacityFlags[i] === 1)) { opacity = opacityMap(camToPoint.length()); } - this.gc.fillStyle = fillStylePrefix + opacity + ')'; - this.gc.strokeStyle = strokeStylePrefix + opacity + ')'; + this.gc.fillStyle = this.styleStringFromRGBA( + lrc.fillColors[i * 3], lrc.fillColors[i * 3 + 1], + lrc.fillColors[i * 3 + 2], opacity); + this.gc.strokeStyle = this.styleStringFromRGBA( + lrc.strokeColors[i * 3], lrc.strokeColors[i * 3 + 1], + lrc.strokeColors[i * 3 + 2], opacity); this.gc.lineWidth = LABEL_STROKE_WIDTH; this.gc.strokeText(text, x, y); this.gc.lineWidth = LABEL_FILL_WIDTH; @@ -141,6 +138,11 @@ export class ScatterPlotVisualizerCanvasLabels implements } } + private styleStringFromRGBA(r: number, g: number, b: number, a: number): + string { + return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; + } + onResize(newWidth: number, newHeight: number) { let dpr = window.devicePixelRatio; d3.select(this.canvas) |