From f51ca77dcea14bafe4126b5cf7b092db6d3c2c5b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 26 Mar 2019 22:37:24 -0400
Subject: a bunch more cleanup

---
 src/client/views/nodes/HistogramBoxPrimitives.tsx | 333 +++++++++-------------
 1 file changed, 128 insertions(+), 205 deletions(-)

(limited to 'src/client/views/nodes/HistogramBoxPrimitives.tsx')

diff --git a/src/client/views/nodes/HistogramBoxPrimitives.tsx b/src/client/views/nodes/HistogramBoxPrimitives.tsx
index a8ada99a4..8c5969938 100644
--- a/src/client/views/nodes/HistogramBoxPrimitives.tsx
+++ b/src/client/views/nodes/HistogramBoxPrimitives.tsx
@@ -1,18 +1,17 @@
 import React = require("react")
+import { computed, observable, runInAction } from "mobx";
+import { observer } from "mobx-react";
+import { Utils as DashUtils } from '../../../Utils';
+import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel";
 import { ChartType } from '../../northstar/model/binRanges/VisualBinRange';
-import { AggregateFunction, Bin, Brush, DoubleValueAggregateResult, HistogramResult, MarginAggregateParameters, MarginAggregateResult } from "../../northstar/model/idea/idea";
+import { AggregateFunction, Bin, Brush, HistogramResult, MarginAggregateParameters, MarginAggregateResult } from "../../northstar/model/idea/idea";
 import { ModelHelpers } from "../../northstar/model/ModelHelpers";
+import { ArrayUtil } from "../../northstar/utils/ArrayUtil";
 import { LABColor } from '../../northstar/utils/LABcolor';
 import { PIXIRectangle } from "../../northstar/utils/MathUtil";
-import { SizeConverter } from "../../northstar/utils/SizeConverter";
 import { StyleConstants } from "../../northstar/utils/StyleContants";
-import "./HistogramBox.scss";
 import { HistogramBox } from "./HistogramBox";
-import { computed, runInAction, observable, trace } from "mobx";
-import { ArrayUtil } from "../../northstar/utils/ArrayUtil";
-import { Utils as DashUtils } from '../../../Utils';
-import { observer } from "mobx-react";
-
+import "./HistogramBox.scss";
 
 export interface HistogramBoxPrimitivesProps {
     HistoBox: HistogramBox;
@@ -24,80 +23,63 @@ export class HistogramBoxPrimitives extends React.Component<HistogramBoxPrimitiv
 
     @computed
     get selectedPrimitives() {
-        return this._selectedPrims.map((bp) => this.drawBorder(bp.Rect, StyleConstants.OPERATOR_BACKGROUND_COLOR));
+        return this._selectedPrims.map((bp) => this.drawRect(bp.Rect, undefined, () => { }, "border"));
     }
     @computed
     get binPrimitives() {
-        if (!this.props.HistoBox.HistoOp || !(this.props.HistoBox.HistoOp.Result instanceof HistogramResult) || !this.props.HistoBox.SizeConverter)
+        let histoOp = this.props.HistoBox.HistoOp;
+        let histoResult = this.props.HistoBox.HistogramResult;
+        if (!histoOp || !histoResult || !this.props.HistoBox.SizeConverter || !histoResult.bins)
             return (null);
+
         let prims: JSX.Element[] = [];
-        let allBrushIndex = ModelHelpers.AllBrushIndex(this.props.HistoBox.HistoOp.Result);
-        for (let key in this.props.HistoBox.HistoOp.Result.bins) {
-            if (this.props.HistoBox.HistoOp.Result.bins.hasOwnProperty(key)) {
-                let drawPrims = new HistogramBinPrimitiveCollection(key, this.props.HistoBox);
-                let filterModel = ModelHelpers.GetBinFilterModel(this.props.HistoBox.HistoOp.Result.bins![key], allBrushIndex, this.props.HistoBox.HistoOp.Result, this.props.HistoBox.HistoOp.X, this.props.HistoBox.HistoOp.Y);
-
-                this.props.HistoBox.HitTargets.setValue(drawPrims.HitGeom, filterModel);
-
-                drawPrims.BinPrimitives.filter(bp => bp.DataValue && bp.BrushIndex !== allBrushIndex).map(binPrimitive => {
-                    let toggleFilter = () => {
-                        if ([filterModel].filter(h => ArrayUtil.Contains(this.props.HistoBox.HistoOp!.FilterModels, h)).length > 0) {
-                            let bp = ArrayUtil.FirstOrDefault<HistogramBinPrimitive>(drawPrims.BinPrimitives, (bp: HistogramBinPrimitive) => bp.BrushIndex == allBrushIndex);
-                            if (bp && bp.DataValue) {
-                                this._selectedPrims.splice(this._selectedPrims.indexOf(bp), 1);
-                            }
-                            this.props.HistoBox.HistoOp!.RemoveFilterModels([filterModel]);
-                        }
-                        else {
-                            let bp = ArrayUtil.FirstOrDefault<HistogramBinPrimitive>(drawPrims.BinPrimitives, (bp: HistogramBinPrimitive) => bp.BrushIndex == allBrushIndex);
-                            if (bp && bp.DataValue) {
-                                this._selectedPrims.push(bp!);
-                            }
-                            this.props.HistoBox.HistoOp!.AddFilterModels([filterModel]);
-                        }
+        let allBrushIndex = ModelHelpers.AllBrushIndex(histoResult);
+        for (let key in Object.keys(histoResult.bins)) {
+            let drawPrims = new HistogramBinPrimitiveCollection(histoResult.bins![key], this.props.HistoBox);
+            let filterModel = ModelHelpers.GetBinFilterModel(histoResult.bins[key], allBrushIndex, histoResult, histoOp.X, histoOp.Y);
+
+            this.props.HistoBox.HitTargets.setValue(drawPrims.HitGeom, filterModel);
+
+            let allBrushPrim = ArrayUtil.FirstOrDefault<HistogramBinPrimitive>(drawPrims.BinPrimitives, (bp: HistogramBinPrimitive) => bp.BrushIndex == allBrushIndex);
+            if (allBrushPrim && allBrushPrim.DataValue) {
+                let toggleFilter = () => {
+                    if (ArrayUtil.Contains(histoOp!.FilterModels, filterModel)) {
+                        this._selectedPrims.splice(this._selectedPrims.indexOf(allBrushPrim!), 1);
+                        histoOp!.RemoveFilterModels([filterModel]);
+                    }
+                    else {
+                        this._selectedPrims.push(allBrushPrim!);
+                        histoOp!.AddFilterModels([filterModel]);
                     }
-                    prims.push(this.drawRect(binPrimitive.Rect, binPrimitive.Color, () => runInAction(toggleFilter)));
-                    prims.push(this.drawRect(binPrimitive.MarginRect, StyleConstants.MARGIN_BARS_COLOR, () => runInAction(toggleFilter)));
-                });
+                }
+                drawPrims.BinPrimitives.filter(bp => bp.DataValue && bp.BrushIndex !== allBrushIndex).map(bp =>
+                    prims.push(
+                        this.drawRect(bp.Rect, bp.Color, () => runInAction(toggleFilter), "bar"),
+                        this.drawRect(bp.MarginRect, StyleConstants.MARGIN_BARS_COLOR, () => runInAction(toggleFilter), "bar")));
             }
         }
+
         return prims;
     }
-    drawBorder(r: PIXIRectangle, color: number) {
-        return <div key={DashUtils.GenerateGuid()} className="histogramboxprimitive-border"
-            style={{
-                position: "absolute",
-                transform: `translate(${r.x}px,${r.y}px)`,
-                width: `${r.width - 1}`,
-                height: `${r.height}`,
-                border: "1px",
-                borderStyle: "solid",
-                pointerEvents: "none",
-                borderColor: `${LABColor.RGBtoHexString(color)}`
-            }}
-        />
-    }
 
-    drawRect(r: PIXIRectangle, color: number, tapHandler: () => void) {
-        return <div key={DashUtils.GenerateGuid()} onPointerDown={(e: React.PointerEvent) => { if (e.button == 0) tapHandler() }}
+    drawRect(r: PIXIRectangle, color: number | undefined, tapHandler: () => void, classExt: string) {
+        return <div key={DashUtils.GenerateGuid()} className={`histogramboxprimitives-+${classExt}`} onPointerDown={(e: React.PointerEvent) => { if (e.button == 0) tapHandler() }}
             style={{
-                position: "absolute",
                 transform: `translate(${r.x}px,${r.y}px)`,
                 width: `${r.width - 1}`,
                 height: `${r.height}`,
-                background: `${LABColor.RGBtoHexString(color)}`
+                background: color ? `${LABColor.RGBtoHexString(color)}` : ""
             }}
         />
     }
     render() {
-        return <div>
+        return <div className="histogramboxprimitives-container">
             {this.binPrimitives}
             {this.selectedPrimitives}
         </div>
     }
 }
 
-
 class HistogramBinPrimitive {
     constructor(init?: Partial<HistogramBinPrimitive>) {
         Object.assign(this, init);
@@ -117,114 +99,89 @@ export class HistogramBinPrimitiveCollection {
     private _histoBox: HistogramBox;
     private get histoOp() { return this._histoBox.HistoOp!; }
     private get histoResult() { return this.histoOp.Result as HistogramResult; }
+    private get sizeConverter() { return this._histoBox.SizeConverter!; }
     public BinPrimitives: Array<HistogramBinPrimitive> = new Array<HistogramBinPrimitive>();
     public HitGeom: PIXIRectangle = PIXIRectangle.EMPTY;
 
-    constructor(key: string, histoBox: HistogramBox) {
+    constructor(bin: Bin, histoBox: HistogramBox) {
         this._histoBox = histoBox;
-        let bin = this.histoResult.bins![key];
-
-        var overlapBrushIndex = ModelHelpers.OverlapBrushIndex(this.histoResult);
-        var orderedBrushes = new Array<Brush>();
-        orderedBrushes.push(this.histoResult.brushes![0]);
-        orderedBrushes.push(this.histoResult.brushes![overlapBrushIndex]);
-        for (var b = 0; b < this.histoResult.brushes!.length; b++) {
-            var brush = this.histoResult.brushes![b];
-            if (brush.brushIndex != 0 && brush.brushIndex != overlapBrushIndex) {
-                orderedBrushes.push(brush);
+        let brushing = this.setupBrushing(bin, this.histoOp.Normalization); // X= 0, Y = 1, V = 2
+
+        brushing.orderedBrushes.reduce((brushFactorSum, brush) => {
+            switch (histoBox.ChartType) {
+                case ChartType.VerticalBar: return this.createVerticalBarChartBinPrimitives(bin, brush, brushing.maxAxis, this.histoOp.Normalization);
+                case ChartType.HorizontalBar: return this.createHorizontalBarChartBinPrimitives(bin, brush, brushing.maxAxis, this.histoOp.Normalization);
+                case ChartType.SinglePoint: return this.createSinglePointChartBinPrimitives(bin, brush);
+                case ChartType.HeatMap: return this.createHeatmapBinPrimitives(bin, brush, brushFactorSum);
             }
-        }
-        var binBrushMaxAxis = this.getBinBrushAxisRange(bin, orderedBrushes, this.histoOp.Normalization); // X= 0, Y = 1
-
-        var brushFactorSum: number = 0;
-        for (var b = 0; b < orderedBrushes.length; b++) {
-            var brush = orderedBrushes[b];
-            var valueAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.V, this.histoResult, brush.brushIndex!);
-            var doubleRes = ModelHelpers.GetAggregateResult(bin, valueAggregateKey) as DoubleValueAggregateResult;
-            var unNormalizedValue = (doubleRes != null && doubleRes.hasResult) ? doubleRes.result : null;
-            if (unNormalizedValue)
-                switch (histoBox.ChartType) {
-                    case ChartType.VerticalBar:
-                        this.createVerticalBarChartBinPrimitives(bin, brush, binBrushMaxAxis, this.histoOp.Normalization, histoBox.SizeConverter!); // X = 0, Y = 1, NOne = -1
-                        break;
-                    case ChartType.HorizontalBar:
-                        this.createHorizontalBarChartBinPrimitives(bin, brush, binBrushMaxAxis, this.histoOp.Normalization, histoBox.SizeConverter!);
-                        break;
-                    case ChartType.SinglePoint:
-                        this.createSinlgePointChartBinPrimitives(bin, brush, unNormalizedValue, histoBox.SizeConverter!);
-                        break;
-                    case ChartType.HeatMap:
-                        var normalizedValue = (unNormalizedValue - histoBox.MinValue) / (Math.abs((histoBox.MaxValue - histoBox.MinValue)) < HistogramBinPrimitiveCollection.TOLERANCE ?
-                            unNormalizedValue : histoBox.MaxValue - histoBox.MinValue);
-                        brushFactorSum = this.createHeatmapBinPrimitives(bin, brush, unNormalizedValue, brushFactorSum, normalizedValue, histoBox.SizeConverter!);
-                }
-        }
+        }, 0);
 
         // adjust brush rects (stacking or not)
-        var sum: number = 0;
         var allBrushIndex = ModelHelpers.AllBrushIndex(this.histoResult);
         var filteredBinPrims = this.BinPrimitives.filter(b => b.BrushIndex != allBrushIndex && b.DataValue != 0.0);
-        var count: number = filteredBinPrims.length;
-        filteredBinPrims.map(fbp => {
+        filteredBinPrims.reduce((sum, fbp) => {
             if (histoBox.ChartType == ChartType.VerticalBar) {
                 if (this.histoOp.X.AggregateFunction == AggregateFunction.Count) {
                     fbp.Rect = new PIXIRectangle(fbp.Rect.x, fbp.Rect.y - sum, fbp.Rect.width, fbp.Rect.height);
                     fbp.MarginRect = new PIXIRectangle(fbp.MarginRect.x, fbp.MarginRect.y - sum, fbp.MarginRect.width, fbp.MarginRect.height);
-                    sum += fbp.Rect.height;
+                    return sum + fbp.Rect.height;
                 }
                 if (this.histoOp.Y.AggregateFunction == AggregateFunction.Avg) {
                     var w = fbp.Rect.width / 2.0;
-                    fbp.Rect = new PIXIRectangle(fbp.Rect.x + sum, fbp.Rect.y, fbp.Rect.width / count, fbp.Rect.height);
+                    fbp.Rect = new PIXIRectangle(fbp.Rect.x + sum, fbp.Rect.y, fbp.Rect.width / filteredBinPrims.length, fbp.Rect.height);
                     fbp.MarginRect = new PIXIRectangle(fbp.MarginRect.x - w + sum + (fbp.Rect.width / 2.0), fbp.MarginRect.y, fbp.MarginRect.width, fbp.MarginRect.height);
-                    sum += fbp.Rect.width;
+                    return sum + fbp.Rect.width;
                 }
             }
             else if (histoBox.ChartType == ChartType.HorizontalBar) {
                 if (this.histoOp.X.AggregateFunction == AggregateFunction.Count) {
                     fbp.Rect = new PIXIRectangle(fbp.Rect.x + sum, fbp.Rect.y, fbp.Rect.width, fbp.Rect.height);
                     fbp.MarginRect = new PIXIRectangle(fbp.MarginRect.x + sum, fbp.MarginRect.y, fbp.MarginRect.width, fbp.MarginRect.height);
-                    sum += fbp.Rect.width;
+                    return sum + fbp.Rect.width;
                 }
                 if (this.histoOp.X.AggregateFunction == AggregateFunction.Avg) {
                     var h = fbp.Rect.height / 2.0;
-                    fbp.Rect = new PIXIRectangle(fbp.Rect.x, fbp.Rect.y + sum, fbp.Rect.width, fbp.Rect.height / count);
+                    fbp.Rect = new PIXIRectangle(fbp.Rect.x, fbp.Rect.y + sum, fbp.Rect.width, fbp.Rect.height / filteredBinPrims.length);
                     fbp.MarginRect = new PIXIRectangle(fbp.MarginRect.x, fbp.MarginRect.y - h + sum + (fbp.Rect.height / 2.0), fbp.MarginRect.width, fbp.MarginRect.height);
-                    sum += fbp.Rect.height;
+                    return sum + fbp.Rect.height;
                 }
             }
-        });
+            return 0;
+        }, 0);
         this.BinPrimitives = this.BinPrimitives.reverse();
         var f = this.BinPrimitives.filter(b => b.BrushIndex == allBrushIndex);
         this.HitGeom = f.length > 0 ? f[0].Rect : PIXIRectangle.EMPTY;
     }
-    private getBinBrushAxisRange(bin: Bin, brushes: Array<Brush>, axis: number): number {
-        var binBrushMaxAxis = Number.MIN_VALUE;
-        brushes.forEach((Brush) => {
-            var maxAggregateKey = ModelHelpers.CreateAggregateKey(axis === 0 ? this.histoOp.Y : this.histoOp.X, this.histoResult, Brush.brushIndex!);
-            var aggResult = ModelHelpers.GetAggregateResult(bin, maxAggregateKey) as DoubleValueAggregateResult;
-            if (aggResult != null) {
-                if (aggResult.result! > binBrushMaxAxis)
-                    binBrushMaxAxis = aggResult.result!;
-            }
-        });
-        return binBrushMaxAxis;
+    private setupBrushing(bin: Bin, normalization: number) {
+        var overlapBrushIndex = ModelHelpers.OverlapBrushIndex(this.histoResult);
+        var orderedBrushes = [this.histoResult.brushes![0], this.histoResult.brushes![overlapBrushIndex]];
+        this.histoResult.brushes!.map(brush => brush.brushIndex != 0 && brush.brushIndex != overlapBrushIndex && orderedBrushes.push(brush));
+        return {
+            orderedBrushes,
+            maxAxis: orderedBrushes.reduce((prev, Brush) => {
+                let aggResult = this.histoOp.getValue(normalization, bin, this.histoResult, Brush.brushIndex!);
+                return aggResult != undefined && aggResult > prev ? aggResult : prev;
+            }, Number.MIN_VALUE)
+        };
     }
-    private createHeatmapBinPrimitives(bin: Bin, brush: Brush, unNormalizedValue: number, brushFactorSum: number, normalizedValue: number, sizeConverter: SizeConverter): number {
+    private createHeatmapBinPrimitives(bin: Bin, brush: Brush, brushFactorSum: number): number {
+
+        let unNormalizedValue = this.histoOp!.getValue(2, bin, this.histoResult, brush.brushIndex!);
+        if (unNormalizedValue == undefined)
+            return brushFactorSum;
 
-        var valueAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.V, this.histoResult, ModelHelpers.AllBrushIndex(this.histoResult));
-        var allUnNormalizedValue = ModelHelpers.GetAggregateResult(bin, valueAggregateKey) as DoubleValueAggregateResult;
+        var normalizedValue = (unNormalizedValue - this._histoBox.ValueRange[0]) / (Math.abs((this._histoBox.ValueRange[1] - this._histoBox.ValueRange[0])) < HistogramBinPrimitiveCollection.TOLERANCE ?
+            unNormalizedValue : this._histoBox.ValueRange[1] - this._histoBox.ValueRange[0]);
 
-        var tx = this._histoBox.VisualBinRanges[0].GetValueFromIndex(bin.binIndex!.indices![0]);
-        var xFrom = sizeConverter.DataToScreenX(tx);
-        var xTo = sizeConverter.DataToScreenX(this._histoBox.VisualBinRanges[0].AddStep(tx));
+        let allUnNormalizedValue = this.histoOp.getValue(2, bin, this.histoResult, ModelHelpers.AllBrushIndex(this.histoResult))
 
-        var ty = this._histoBox.VisualBinRanges[1].GetValueFromIndex(bin.binIndex!.indices![1]);
-        var yFrom = sizeConverter.DataToScreenY(ty);
-        var yTo = sizeConverter.DataToScreenY(this._histoBox.VisualBinRanges[1].AddStep(ty));
+        // bcz: are these calls needed?  
+        let [xFrom, xTo] = this.sizeConverter.DataToScreenAxisRange(this._histoBox.VisualBinRanges, 0, bin);
+        let [yFrom, yTo] = this.sizeConverter.DataToScreenAxisRange(this._histoBox.VisualBinRanges, 1, bin);
 
         var returnBrushFactorSum = brushFactorSum;
-        if (allUnNormalizedValue.hasResult) {
-            var brushFactor = (unNormalizedValue / allUnNormalizedValue.result!);
+        if (allUnNormalizedValue != undefined) {
+            var brushFactor = (unNormalizedValue / allUnNormalizedValue);
             returnBrushFactorSum += brushFactor;
             returnBrushFactorSum = Math.min(returnBrushFactorSum, 1.0);
 
@@ -250,95 +207,67 @@ export class HistogramBinPrimitiveCollection {
         return returnBrushFactorSum;
     }
 
-    private createSinlgePointChartBinPrimitives(bin: Bin, brush: Brush, unNormalizedValue: number, sizeConverter: SizeConverter): void {
-        var yAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.Y, this.histoResult, brush.brushIndex!);
-        var xAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.X, this.histoResult, brush.brushIndex!);
-
-        var xValue = ModelHelpers.GetAggregateResult(bin, xAggregateKey) as DoubleValueAggregateResult;
-        if (!xValue.hasResult)
-            return;
-        var xFrom = sizeConverter.DataToScreenX(xValue.result!) - 5;
-        var xTo = sizeConverter.DataToScreenX(xValue.result!) + 5;
+    private createSinglePointChartBinPrimitives(bin: Bin, brush: Brush): number {
+        let unNormalizedValue = this._histoBox.HistoOp!.getValue(2, bin, this.histoResult, brush.brushIndex!);
+        if (unNormalizedValue != undefined) {
+            let [xFrom, xTo] = this.sizeConverter.DataToScreenPointRange(0, bin, ModelHelpers.CreateAggregateKey(this.histoOp.X, this.histoResult, brush.brushIndex!));
+            let [yFrom, yTo] = this.sizeConverter.DataToScreenPointRange(1, bin, ModelHelpers.CreateAggregateKey(this.histoOp.Y, this.histoResult, brush.brushIndex!));
 
-        var yValue = ModelHelpers.GetAggregateResult(bin, yAggregateKey) as DoubleValueAggregateResult;;
-        if (!yValue.hasResult)
-            return;
-        var yFrom = sizeConverter.DataToScreenY(yValue.result!) + 5;
-        var yTo = sizeConverter.DataToScreenY(yValue.result!);
-
-        this.createBinPrimitive(bin, brush, PIXIRectangle.EMPTY, 0, xFrom, xTo, yFrom, yTo, this.baseColorFromBrush(brush), 1, unNormalizedValue);
+            if (xFrom != undefined && yFrom != undefined && xTo != undefined && yTo != undefined)
+                this.createBinPrimitive(bin, brush, PIXIRectangle.EMPTY, 0, xFrom, xTo, yFrom, yTo, this.baseColorFromBrush(brush), 1, unNormalizedValue);
+        }
+        return 0;
     }
 
-    private createVerticalBarChartBinPrimitives(bin: Bin, brush: Brush, binBrushMaxAxis: number, normalization: number, sizeConverter: SizeConverter): void {
-        var yAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.Y, this.histoResult, brush.brushIndex!);
-        var marginParams = new MarginAggregateParameters();
-        marginParams.aggregateFunction = this.histoOp.Y.AggregateFunction;
-        var yMarginAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.Y, this.histoResult,
-            brush.brushIndex!, marginParams);
-        var dataValue = ModelHelpers.GetAggregateResult(bin, yAggregateKey) as DoubleValueAggregateResult;
-
-        if (dataValue != null && dataValue.hasResult) {
-            var yValue = normalization != 0 || binBrushMaxAxis == 0 ? dataValue.result! : (dataValue.result! - 0) / (binBrushMaxAxis - 0) * sizeConverter.DataRanges[1];
-
-            var yFrom = sizeConverter.DataToScreenY(Math.min(0, yValue));
-            var yTo = sizeConverter.DataToScreenY(Math.max(0, yValue));;
-
-            var xValue = this._histoBox.VisualBinRanges[0].GetValueFromIndex(bin.binIndex!.indices![0])!;
-            var xFrom = sizeConverter.DataToScreenX(xValue);
-            var xTo = sizeConverter.DataToScreenX(this._histoBox.VisualBinRanges[0].AddStep(xValue));
+    private createVerticalBarChartBinPrimitives(bin: Bin, brush: Brush, binBrushMaxAxis: number, normalization: number): number {
+        let dataValue = this.histoOp.getValue(1, bin, this.histoResult, brush.brushIndex!);
+        if (dataValue != undefined) {
+            let [yFrom, yValue, yTo] = this.sizeConverter.DataToScreenNormalizedRange(dataValue, normalization, 1, binBrushMaxAxis);
+            let [xFrom, xTo] = this.sizeConverter.DataToScreenAxisRange(this._histoBox.VisualBinRanges, 0, bin);
 
-            var marginResult = ModelHelpers.GetAggregateResult(bin, yMarginAggregateKey) as MarginAggregateResult;
-            var yMarginAbsolute = !marginResult ? 0 : marginResult.absolutMargin!;
+            var yMarginAbsolute = this.getMargin(bin, brush, this.histoOp.Y);
             var marginRect = new PIXIRectangle(xFrom + (xTo - xFrom) / 2.0 - 1,
-                sizeConverter.DataToScreenY(yValue + yMarginAbsolute), 2,
-                sizeConverter.DataToScreenY(yValue - yMarginAbsolute) - sizeConverter.DataToScreenY(yValue + yMarginAbsolute));
+                this.sizeConverter.DataToScreenY(yValue + yMarginAbsolute), 2,
+                this.sizeConverter.DataToScreenY(yValue - yMarginAbsolute) - this.sizeConverter.DataToScreenY(yValue + yMarginAbsolute));
 
             this.createBinPrimitive(bin, brush, marginRect, 0, xFrom, xTo, yFrom, yTo,
-                this.baseColorFromBrush(brush), normalization != 0 ? 1 : 0.6 * binBrushMaxAxis / sizeConverter.DataRanges[1] + 0.4, dataValue.result!);
+                this.baseColorFromBrush(brush), normalization != 0 ? 1 : 0.6 * binBrushMaxAxis / this.sizeConverter.DataRanges[1] + 0.4, dataValue);
         }
+        return 0;
     }
 
-    private createHorizontalBarChartBinPrimitives(bin: Bin, brush: Brush, binBrushMaxAxis: number, normalization: number, sizeConverter: SizeConverter): void {
-        var xAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.X, this.histoResult, brush.brushIndex!);
-        var marginParams = new MarginAggregateParameters();
-        marginParams.aggregateFunction = this.histoOp.X.AggregateFunction;
-        var xMarginAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.X, this.histoResult,
-            brush.brushIndex!, marginParams);
-        var dataValue = ModelHelpers.GetAggregateResult(bin, xAggregateKey) as DoubleValueAggregateResult;
-
-        if (dataValue != null && dataValue.hasResult) {
-            var xValue = normalization != 1 || binBrushMaxAxis == 0 ? dataValue.result! : (dataValue.result! - 0) / (binBrushMaxAxis - 0) * sizeConverter.DataRanges[0];
-            var xFrom = sizeConverter.DataToScreenX(Math.min(0, xValue));
-            var xTo = sizeConverter.DataToScreenX(Math.max(0, xValue));
-
-            var yValue = this._histoBox.VisualBinRanges[1].GetValueFromIndex(bin.binIndex!.indices![1]);
-            var yFrom = yValue;
-            var yTo = this._histoBox.VisualBinRanges[1].AddStep(yValue);
+    private createHorizontalBarChartBinPrimitives(bin: Bin, brush: Brush, binBrushMaxAxis: number, normalization: number): number {
+        let dataValue = this.histoOp.getValue(0, bin, this.histoResult, brush.brushIndex!);
+        if (dataValue != undefined) {
+            let [xFrom, xValue, xTo] = this.sizeConverter.DataToScreenNormalizedRange(dataValue, normalization, 0, binBrushMaxAxis);
+            let [yFrom, yTo] = this.sizeConverter.DataToScreenAxisRange(this._histoBox.VisualBinRanges, 1, bin);
 
-            var marginResult = ModelHelpers.GetAggregateResult(bin, xMarginAggregateKey) as MarginAggregateResult;
-            var xMarginAbsolute = sizeConverter.IsSmall || !marginResult ? 0 : marginResult.absolutMargin!;
-
-            var marginRect = new PIXIRectangle(sizeConverter.DataToScreenX(xValue - xMarginAbsolute),
+            var xMarginAbsolute = this.sizeConverter.IsSmall ? 0 : this.getMargin(bin, brush, this.histoOp.X);
+            var marginRect = new PIXIRectangle(this.sizeConverter.DataToScreenX(xValue - xMarginAbsolute),
                 yTo + (yFrom - yTo) / 2.0 - 1,
-                sizeConverter.DataToScreenX(xValue + xMarginAbsolute) - sizeConverter.DataToScreenX(xValue - xMarginAbsolute),
+                this.sizeConverter.DataToScreenX(xValue + xMarginAbsolute) - this.sizeConverter.DataToScreenX(xValue - xMarginAbsolute),
                 2.0);
 
             this.createBinPrimitive(bin, brush, marginRect, 0, xFrom, xTo, yFrom, yTo,
-                this.baseColorFromBrush(brush), normalization != 1 ? 1 : 0.6 * binBrushMaxAxis / sizeConverter.DataRanges[0] + 0.4, dataValue.result!);
+                this.baseColorFromBrush(brush), normalization != 1 ? 1 : 0.6 * binBrushMaxAxis / this.sizeConverter.DataRanges[0] + 0.4, dataValue);
         }
+        return 0;
+    }
+
+
+    private getMargin(bin: Bin, brush: Brush, axis: AttributeTransformationModel) {
+        var marginParams = new MarginAggregateParameters();
+        marginParams.aggregateFunction = axis.AggregateFunction;
+        var marginAggregateKey = ModelHelpers.CreateAggregateKey(axis, this.histoResult, brush.brushIndex!, marginParams);
+        var marginResult = ModelHelpers.GetAggregateResult(bin, marginAggregateKey) as MarginAggregateResult;
+        return !marginResult ? 0 : marginResult.absolutMargin!;
     }
 
     private createBinPrimitive(bin: Bin, brush: Brush, marginRect: PIXIRectangle,
         marginPercentage: number, xFrom: number, xTo: number, yFrom: number, yTo: number, color: number, opacity: number, dataValue: number) {
-        // hitgeom todo
-
         var binPrimitive = new HistogramBinPrimitive(
             {
-                Rect: new PIXIRectangle(
-                    xFrom,
-                    yTo,
-                    xTo - xFrom,
-                    yFrom - yTo),
+                Rect: new PIXIRectangle(xFrom, yTo, xTo - xFrom, yFrom - yTo),
                 MarginRect: marginRect,
                 MarginPercentage: marginPercentage,
                 BrushIndex: brush.brushIndex,
@@ -350,24 +279,18 @@ export class HistogramBinPrimitiveCollection {
     }
 
     private baseColorFromBrush(brush: Brush): number {
-        var baseColor: number = StyleConstants.HIGHLIGHT_COLOR;
         if (brush.brushIndex == ModelHelpers.RestBrushIndex(this.histoResult)) {
-            baseColor = StyleConstants.HIGHLIGHT_COLOR;
+            return StyleConstants.HIGHLIGHT_COLOR;
         }
         else if (brush.brushIndex == ModelHelpers.OverlapBrushIndex(this.histoResult)) {
-            baseColor = StyleConstants.OVERLAP_COLOR;
+            return StyleConstants.OVERLAP_COLOR;
         }
         else if (brush.brushIndex == ModelHelpers.AllBrushIndex(this.histoResult)) {
-            baseColor = 0x00ff00;
+            return 0x00ff00;
         }
-        else {
-            if (this._histoBox.HistoOp!.BrushColors.length > 0) {
-                baseColor = this._histoBox.HistoOp!.BrushColors[brush.brushIndex! % this._histoBox.HistoOp!.BrushColors.length];
-            }
-            else {
-                baseColor = StyleConstants.HIGHLIGHT_COLOR;
-            }
+        else if (this.histoOp.BrushColors.length > 0) {
+            return this.histoOp.BrushColors[brush.brushIndex! % this.histoOp.BrushColors.length];
         }
-        return baseColor;
+        return StyleConstants.HIGHLIGHT_COLOR;
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2

