Skip to content
Snippets Groups Projects
Select Git revision
  • 53b4e7fe782b9ee91c59f23402ba02ed463014ff
  • stable default protected
  • MA_Pape_2018
  • MA_2018_Lopatin
  • feature/mesh_viewer
  • feature/#468_access_isosurface_scalar
  • feature/#459_default_primitives
  • master protected
  • feature/#470_Create_a_color_lookup_table
  • feature/#473_resize_companion_window
  • feature/#462_do_not_use_arb_extensions
  • feature/#495_Provide_data_for_larger_isosurfaces
  • feature/#323_default_image
  • feature/#480_Create_a_smaller_test_mesh_for_combustion_demo
  • feature/#236_Get_Integration_tests_running_on_CI
  • feature/#447_Copy_standard_assets_to_build_folder
  • 447-copy-standard-assets-to-build-folder-and-remove-resource-path
  • feature/#445_mesh_render_settings_component
  • feature/#251_Make_sure_tests_cpp_is_compiled_once
  • feature/#455_Remove_navigation_and_improve_interaction_for_combustion_demo
  • feature/446_strange_txt_files
  • v18.06.0
  • v18.05.0
  • #251_bad
  • #251_good
  • v18.03.0
  • v18.02.0
  • v18.01.0
  • v17.12.0
  • v17.11.0
  • v17.10.0
  • v17.09.0
  • v17.07.0
33 results

Testing.cmake

Blame
  • radarChart.ts 8.58 KiB
    import * as d3 from "d3";
    import {ScaleLinear} from "d3";
    import Chart, {ChartConfig, ChartConfigParam} from "@/charts/chart.ts";
    
    export type RadarChartConfig = ChartConfig & {
        selectedData: RadarChartSelection[],
        renderTooltip?: (dataPoint: any, tooltip: d3.Selection<d3.BaseType, unknown, HTMLElement, any>) => void,
        axisCircles: number,
        idAccessor: (d: any) => any,
        attributes: { key: string, label: string }[] | [],
    }
    
    export type RadarChartConfigParam = ChartConfigParam & Partial<RadarChartConfig>
    
    type RadarChartSelection = {
        _color: string | null | undefined,
        [key: string]: any
    }
    
    export default class RadarChart extends Chart {
        chartId: string = 'radarChart';
        chart: any
        config: RadarChartConfig
        axes: {
            scale: ScaleLinear<number, number>,
            domain: [number, number],
            label: string,
            key: string,
        }[] = []
    
        constructor(data: any[], _config: RadarChartConfigParam) {
            super(data, _config as ChartConfigParam)
    
            this.config = this.createConfig(_config)
    
            this.initVis()
        }
    
        private setConfig(_config: RadarChartConfigParam) {
            this.config = this.createConfig(_config)
        }
    
        private createConfig(_config: RadarChartConfigParam): RadarChartConfig {
            return {
                ..._config,
                parentElement: typeof _config.parentElement === 'string' ? document.querySelector(_config.parentElement) as HTMLElement : _config.parentElement,
                containerWidth: _config.containerWidth || 500,
                containerHeight: _config.containerHeight || 140,
                margin: _config.margin || {top: 10, bottom: 30, right: 10, left: 30},
                tooltipPadding: _config.tooltipPadding || 15,
                axisCircles: _config.axisCircles || 2,
                selectedData: _config.selectedData || [],
                attributes: _config.attributes || [],
                idAccessor: _config.idAccessor || (() => null),
            }
        }
    
        initVis() {
            let vis = this;
            vis.config.parentElement.innerHTML += `
                <svg id="${this.chartId}"></svg>
            `;
            vis.config.parentElement.innerHTML += `
                <div id="tooltip-radar-chart" class="tooltip"></div>
            `;
    
            const svg = d3.select(`#${this.chartId}`)
                .attr('width', vis.config.containerWidth)
                .attr('height', vis.config.containerHeight)
                .attr('transform', `translate(${vis.config.margin.left},${vis.config.margin.top})`)
    
            vis.chart = svg.append('g')
    
            for (const attribute of vis.config.attributes) {
                const domain: [number, number] = [0, (d3.max(vis.data, (d: any) => d[attribute.key] as number) as number)]
                const scale = d3.scaleLinear(
                    domain,
                    [0, vis.axisLength],
                )
                vis.axes.push({
                    scale,
                    domain,
                    label: attribute.label,
                    key: attribute.key,
                })
            }
        }
    
        updateVis(selectedData: RadarChartSelection[]): void {
            this.config.selectedData = selectedData;
    
            this.drawData();
        }
    
        private getPreparedData(): {
            data: RadarChartSelection,
            axesValues: { label: string, r: number, value: number }[]
        }[] {
            return this.config.selectedData.map(
                (d: any) => ({
                    data: d,
                    axesValues: this.axes.map(axis => (
                        {
                            label: axis.label,
                            r: axis.scale(d[axis.key]),
                            value: d[axis.key],
                        }
                    ))
                })
            );
        }
    
        private get chartCenter() {
            return Math.min(this.config.containerWidth, this.config.containerHeight) / 2
        }
    
        private get axisLength() {
            if (this.config.containerWidth < this.config.containerHeight) {
                return this.width() / 2
            }
            return this.height() / 2
        }
    
        renderVis(): void {
            let vis: RadarChart = this;
    
            const axisGrid = vis.chart.append("g")
                .attr("class", "axisWrapper")
                .attr('transform', `translate(${vis.chartCenter},${vis.chartCenter})`)
    
            const axes = axisGrid.selectAll('.axis')
                .data(vis.axes)
                .enter()
                .append('g')
                .attr('class', 'axis')
    
            axes.append("path")
                .attr("pointer-events", "none")
                .attr("d", (_: any, index: number) => d3.lineRadial()
                    ([[0, 0], [Math.PI * 2 * index / vis.axes.length, this.axisLength]])
                )
            axes.append('text')
                .attr("x", (_: any, index: number) => Math.sin(2 * Math.PI * (index / vis.axes.length)) * (this.axisLength + 10))
                .attr("y", (_: any, index: number) => -Math.cos(2 * Math.PI * (index / vis.axes.length)) * (this.axisLength + 10))
                .attr('text-anchor', 'middle')
                .attr('alignment-baseline', 'middle')
                .attr('font-size', 12)
                .attr('fill', 'black')
                .text((d: any) => d.label)
    
            this.drawData();
        }
    
        private drawData() {
            let dataWrapper = this.chart.selectAll(".dataWrapper")
            if (dataWrapper.empty()) {
                dataWrapper = this.chart.append("g")
                    .attr("class", "dataWrapper")
                    .attr('transform', `translate(${this.chartCenter},${this.chartCenter})`)
            }
    
            const preparedData = this.getPreparedData()
    
            dataWrapper.selectAll('.data')
                .data(preparedData, (d: any) => this.config.idAccessor(d.data))
                .join(
                    (enter: any) => {
                        const data = enter.append("g")
                            .attr("class", "data")
    
                        data
                            .append("path")
                            .attr("d", (d: any) => {
                                const data = d.axesValues.map((d: any) => d.r)
                                return d3.lineRadial()
                                    .angle((_, index) => Math.PI * 2 / this.axes.length * index)
                                    .radius((value) => value || 0)
                                    .curve(d3.curveCardinalClosed.tension(0.6))
                                    ([...data, data[0]])
                            })
                            .attr('fill', (d: any) => {
                                const color = d3.color(d.data._color)
                                if (!color) {
                                    return "rgba(50,50,50,0.1)"
                                }
                                return color.copy({opacity: 0.2}).toString()
                            })
                            .attr('stroke', (d: any) => d.data._color)
                            .attr('stroke-width', 3)
    
                        data.selectAll('.dataPoint')
                            .data((d: any) => d.axesValues.map((value: any) => ({
                                ...value,
                                data: d.data,
                            })))
                            .join(
                                enter => enter.append("circle"),
                                update => update,
                                exit => exit.remove()
                            )
                            .attr("class", "dataPoint")
                            .attr("r", 5)
                            .attr("cx", (data: {
                                r: number,
                            }, index: number) => Math.sin(2 * Math.PI * (index / this.axes.length)) * data.r)
                            .attr("cy", (data: {
                                r: number,
                            }, index: number) => -Math.cos(2 * Math.PI * (index / this.axes.length)) * data.r)
                            .attr('fill', (d: any) => d.data._color)
                            .on('mouseover', (_: Event, d: any) => {
                                const element = d3.select('#tooltip-radar-chart')
                                    .style('display', 'block')
                                if (!this.config.renderTooltip) return
                                this.config.renderTooltip(d, element)
                            })
                            .on('mousemove', (event: any) => {
                                d3.select('#tooltip-radar-chart')
                                    .style('left', (event.layerX + this.config.tooltipPadding) + 'px')
                                    .style('top', (event.layerY + this.config.tooltipPadding) + 'px')
                            })
                            .on('mouseleave', (_: Event) => {
                                d3.select('#tooltip-radar-chart').style('display', 'none');
                            })
                    },
                    (update: any) => update,
                    (exit: any) => exit.remove()
                )
    
    
        }
    }