autodesk-platform-services / aps-iot-extensions-demo

APS DataViz Extensions Demo:Visualizing IoT sensor data.
https://aps-iot-extensions-demo.autodesk.io
MIT License
11 stars 6 forks source link

Using multiple sprite styles causes rendering issues with sprites #16

Open RustyRaptor opened 10 months ago

RustyRaptor commented 10 months ago

I realize this could be the wrong place to report this. Let me know if I need to move this to another repo or a support channel.

https://github.com/autodesk-platform-services/aps-iot-extensions-demo/assets/7911442/608d5cbb-8714-415a-85f4-a92192f3aa73

Here is some of the output I get if I log the ViewableData

_spritesMap:

{
    "/predicted_failure.png": {
        "width": 648,
        "height": 648,
        "x": 0,
        "y": 0,
        "rot": false
    },
    "/predicted_anomaly.png": {
        "width": 648,
        "height": 648,
        "x": 650,
        "y": 0,
        "rot": false
    },
    "/normal.png": {
        "width": 648,
        "height": 648,
        "x": 0,
        "y": 0,
        "rot": false
    }
}

_viewablesMap:

new Map([
    [
        1000000,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 1,
                    "g": 1,
                    "b": 1
                },
                "url": "/predicted_failure.png",
                "highlightedColor": {
                    "r": 1,
                    "g": 1,
                    "b": 1
                },
                "highlightedUrl": "/predicted_failure.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": -52,
                "y": 10,
                "z": -12.15
            },
            "_dbId": 1000000
        }
    ],
    [
        1000001,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 1,
                    "g": 1,
                    "b": 1
                },
                "url": "/predicted_anomaly.png",
                "highlightedColor": {
                    "r": 1,
                    "g": 1,
                    "b": 1
                },
                "highlightedUrl": "/predicted_anomaly.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": -26,
                "y": 10,
                "z": -12.15
            },
            "_dbId": 1000001
        }
    ],
    [
        1000002,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 0.30196078431372547,
                    "g": 1,
                    "b": 0
                },
                "url": "/normal.png",
                "highlightedColor": {
                    "r": 0.30196078431372547,
                    "g": 1,
                    "b": 0
                },
                "highlightedUrl": "/normal.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": 0,
                "y": 10,
                "z": -12.15
            },
            "_dbId": 1000002
        }
    ],
    [
        1000003,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 1,
                    "g": 1,
                    "b": 0
                },
                "url": "/normal.png",
                "highlightedColor": {
                    "r": 1,
                    "g": 1,
                    "b": 0
                },
                "highlightedUrl": "/normal.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": 26,
                "y": 10,
                "z": -12.15
            },
            "_dbId": 1000003
        }
    ],
    [
        1000004,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 0.30196078431372547,
                    "g": 1,
                    "b": 0
                },
                "url": "/normal.png",
                "highlightedColor": {
                    "r": 0.30196078431372547,
                    "g": 1,
                    "b": 0
                },
                "highlightedUrl": "/normal.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": 52,
                "y": 10,
                "z": -12.15
            },
            "_dbId": 1000004
        }
    ],
    [
        1000005,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 1,
                    "g": 0,
                    "b": 0
                },
                "url": "/normal.png",
                "highlightedColor": {
                    "r": 1,
                    "g": 0,
                    "b": 0
                },
                "highlightedUrl": "/normal.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": 78,
                "y": 10,
                "z": -12.15
            },
            "_dbId": 1000005
        }
    ],
    [
        1000006,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 1,
                    "g": 1,
                    "b": 1
                },
                "url": "/predicted_anomaly.png",
                "highlightedColor": {
                    "r": 1,
                    "g": 1,
                    "b": 1
                },
                "highlightedUrl": "/predicted_anomaly.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": -26,
                "y": -33,
                "z": -12.15
            },
            "_dbId": 1000006
        }
    ],
    [
        1000007,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 1,
                    "g": 1,
                    "b": 1
                },
                "url": "/predicted_failure.png",
                "highlightedColor": {
                    "r": 1,
                    "g": 1,
                    "b": 1
                },
                "highlightedUrl": "/predicted_failure.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": 0,
                "y": -33,
                "z": -12.15
            },
            "_dbId": 1000007
        }
    ],
    [
        1000008,
        {
            "_style": {
                "type": 1,
                "color": {
                    "r": 0.30196078431372547,
                    "g": 1,
                    "b": 0
                },
                "url": "/normal.png",
                "highlightedColor": {
                    "r": 0.30196078431372547,
                    "g": 1,
                    "b": 0
                },
                "highlightedUrl": "/normal.png",
                "spriteUrls": {}
            },
            "_position": {
                "x": 26,
                "y": -33,
                "z": -12.15
            },
            "_dbId": 1000008
        }
    ]
])

Some parts of my code:

_refreshSprites()


        _refreshSprites() {
                this._dataVizExt.removeAllViewables();
                if (!this.dataView) {
                        return;
                }
                let viewableData = new Autodesk.DataVisualization.Core.ViewableData();
                viewableData.spriteSize = 32;
                this._dbIdToSensorId.clear();
                let dbid = 1000000;
                for (const [sensorId, sensor] of this.dataView.getSensors().entries()) {
                        viewableData = this._process_sensor(sensorId, sensor, dbid, viewableData);
                        if (!this.sensor_id_to_sensor_map.has(sensorId)) {
                                this.sensor_id_to_sensor_map.set(sensorId, sensor);
                        }
                        dbid++;
                }
                // if the issues are loaded set the style
                if (this.issues_loaded) {
                        this.set_style = true;
                }

                viewableData.finish().then(() => {
                        this._dataVizExt.addViewables(viewableData);
                });
                console.log(viewableData);

_process_sensor()

        _process_sensor(sensorId, sensor, dbid, viewableData) {
                this._dbIdToSensorId.set(dbid, sensorId);
                const { x, y, z } = sensor.location;
                if (this.issues_loaded && !this.set_style) {
                        console.log("setting style...");
                        console.log(this._set_sensor_style_and_map_issues(sensorId));
                        this.sensor_to_styles_map.set(
                                sensorId,
                                this._set_sensor_style_and_map_issues(sensorId)
                        );
                }
                let viewable = this.create_viewable(x, y, z, sensorId, dbid);
                viewableData.addViewable(viewable);
                return viewableData;
        }

_set_sensor_style_and_map_issues()

       _set_sensor_style_and_map_issues(sensorId) {

                // if its already in the map return the style
                if (this.sensor_to_styles_map.has(sensorId)) {
                        return this.sensor_to_styles_map.get(sensorId);
                }
                // this.sensor_to_styles_map.set(sensorId, this._createVisualStyle(0x4dff00));
                const manual_icon = '/normal.png';
                const predicted_failure_icon = '/predicted_failure.png';
                const predicted_anomaly_icon = '/predicted_anomaly.png';

                // filter issues for this sensor that are not closed
                const sensor_issues = this.issues.filter(
                        issue => issue.location == sensorId 
                        && issue.status != "CLOSE"
                );

                // add all issues to the sensor_id_to_issues_map
                for (const issue of sensor_issues) {
                        this._add_issue_to_sensor_map(sensorId, issue);
                }

                // if there are no issues for this sensor, set it to green
                if (sensor_issues.length == 0) {

                        // continue to next sensor
                        return this._createVisualStyle(
                                0x4dff00,
                                manual_icon
                        );
                }

                // if there are any manual failure issues, set it to red
                const manual_failure_issues = sensor_issues.filter(
                        issue => issue.reportType == "Manual"
                        && issue.defectType == "Failure"
                );
                if (manual_failure_issues.length > 0) {
                        // continue to next sensor
                        return this._createVisualStyle(
                                0xff0000,
                                manual_icon
                        );
                }

                // if there are any manual anomaly issues, set it to yellow
                const manual_anomaly_issues = sensor_issues.filter(
                        issue => issue.reportType == "Manual"
                        && issue.defectType == "Anomaly"
                );
                if (manual_anomaly_issues.length > 0) {

                        // continue to next sensor
                        return this._createVisualStyle(
                                0xffff00,
                                manual_icon
                        );
                }

                // if there are any predicted failure issues, set it to predicted failure icon
                const predicted_failure_issues = sensor_issues.filter(
                        issue => issue.reportType == "Predicted"
                        && issue.defectType == "Failure"
                );      
                if (predicted_failure_issues.length > 0) {
                        // continue to next sensor
                        return this._createVisualStyle(
                                undefined,
                                predicted_failure_icon
                        );
                }

                // if there are any predicted anomaly issues, set it to predicted anomaly icon
                const predicted_anomaly_issues = sensor_issues.filter(
                        issue => issue.reportType == "Predicted"
                        && issue.defectType == "Anomaly"
                );
                if (predicted_anomaly_issues.length > 0) {
                        // continue to next sensor
                        return this._createVisualStyle(
                                undefined,
                                predicted_anomaly_icon
                        );
                }

                // otherwise make it green
                return this._createVisualStyle(
                        0x4dff00,
                        manual_icon
                );
        }

create_viewable()

        create_viewable(x, y, z, sensorId, dbid) {
                let viewable = new Autodesk.DataVisualization.Core.SpriteViewable(
                        new THREE.Vector3(x, y, z),
                        this._createVisualStyle(
                                0x4dff00,
                                '/normal.png'
                        ),
                        dbid
                );
                if (this.sensor_to_styles_map.has(sensorId)) {
                        viewable = new Autodesk.DataVisualization.Core.SpriteViewable(
                                new THREE.Vector3(x, y, z),
                                this.sensor_to_styles_map.get(sensorId),
                                dbid
                        );
                }
                return viewable;
        }

_create_visual_style()

        _createVisualStyle(color, icon_url) {
                const DataVizCore = Autodesk.DataVisualization.Core;
                const viewableType = DataVizCore.ViewableType.SPRITE;
                let spriteColor = undefined;

                if (color == undefined) {
                        spriteColor = undefined;
                } else {
                        spriteColor = new THREE.Color(color);
                }
                const spriteIconUrl = icon_url;
                return new DataVizCore.ViewableStyle(
                        viewableType,
                        spriteColor,
                        spriteIconUrl,
                        spriteColor,
                        spriteIconUrl,
                        undefined
                );
        }

update() and constructor

export class SensorSpritesExtension extends UIBaseExtension {
        constructor(viewer, options) {
                super(viewer, options);
                this._onSpriteClicked = this._onSpriteClicked.bind(this);
                this._onSpriteHovered = this._onSpriteHovered.bind(this);
                this.show_sensor_info = this._show_sensor_info.bind(this);
                this._dbIdToSensorId = new Map();
                this.update = this.update.bind(this);
                this.issues = [];
                this.sensors = [];
                this.set_style = false;
                this.issues_loaded = false;
                this.sensor_to_styles_map = new Map();
                this.sensor_id_to_issues_map = new Map();
                this.sensor_id_to_sensor_map = new Map();
                this.all_dialogs = [];
        }

        onDataViewChanged(oldDataView, newDataView) { this.update(); }

        update() {
                if (this.isActive()) {
                        this._refreshSprites();
                }

                if (this.dataView && window.location.hash.startsWith('#4473-CHLR')) {
                        // hide all dialogs in the all_dialogs array
                        for (const dialog of this.all_dialogs) {
                                dialog.setVisible(false);
                        }
                        const sensor_id_string =
                                window.location.hash.split('#')[1];

                        const dialog_contents =
                                this._create_dialog_contents(sensor_id_string);

                        const new_dialog = this._create_dialog_at(
                                50,
                                50,
                                dialog_contents,
                                sensor_id_string
                        );

                        this.all_dialogs.push(new_dialog);
                }
        }
RustyRaptor commented 10 months ago

Well going back and starting over has fixed the issue. So I guess this isn't really a bug with APS but just my implementation is broken. I'll try to figure out why that is.

RustyRaptor commented 10 months ago

Ok so turns out that the reason this was happening was because the images used for the sprites were taking too long to load because they are too big (600 by 600)ish. I noticed this when I started changing the images around the issue started again. Reducing the size of the images to 32 by 32 fixed the issue. I'm sure bigger sizes would work but I decided to match the size I was using for the sprites options.

I am wondering if maybe the implementation needs to be different to avoid this issue entirely. Maybe something with the order in which things are being done is causing the sprites to refresh way sooner than the images loading? Or does this have something to do with the 3D viewer rendering too fast? I feel like I am in way over my head trying to figure this out now.