Issue with changing feature colors in 3D using UniqueValueRenderer in SceneView

I’m facing an issue while trying to apply a UniqueValueRenderer on a 3D FeatureLayer in a SceneView. My goal is to change the color of the features based on an alert field coming from a CSV file.

The interesting part is that, as the date on the timeslider changes, the color filling the polygons changes based on the alert value.

I have managed to get it working perfectly in 2D (MapView), but when switching to 3D, the layer is not displayed, and I get the following error in the developer tab:

Graphic in layer 19227fb6798-layer-0 has no symbol and will not render.

In some combinations I’ve tried by changing parameters in the code below, I managed to display the layer at some point, but all the entities had the same color.

What I’m doing:

  1. Loading a CSV file containing alert data (values like “A5”, “A4”, etc.) linked to an ID (comarca_sg) field in the layer.

  2. Using a UniqueValueRenderer to change the color of the features based on the comarca_sg field and the alert value from the CSV.

  3. The function getColorBasedOnAlert assigns a color depending on the alert value (“A5” = dark red, “A4” = light red, etc.).

The problem:

• In 2D, the colors change correctly for each feature.
• In 3D (SceneView), **the layer is not displayed ** or all the features render with the same color, even though the same UniqueValueRenderer is applied.

Here’s the code:

require([
  "esri/Map",
  "esri/views/MapView",
  "esri/views/SceneView",
  "esri/layers/FeatureLayer",
  "esri/widgets/TimeSlider",
  "esri/geometry/Extent",
  "esri/core/watchUtils",
  "esri/request"
], function(Map, MapView,SceneView, FeatureLayer, TimeSlider, Extent, watchUtils, esriRequest) {

  // Crear el mapa y la vista de escena
  var map = new Map({
    basemap: "gray-vector", // Basemap actualizado
    ground: "world-elevation"
  });

// Create the SceneView and set initial camera
  const view = new SceneView({
    container: "viewDiv",
    map: map,
    camera: {
      position: {
        latitude: 40.5,
        longitude: -3.7,
        z: 3500000
      },
      tilt: 0,
      heading: 1
    },


    highlightOptions: {
      color: "cyan"
    }
  });


// VISOR EN 2D
// const view = new MapView({
//   container: "viewDiv",
//   map: map,
//   zoom: 5, // Ajusta el zoom para un nivel adecuado de detalle
//   center: [-3.7038, 40.4168] // Coordenadas de Madrid, España (longitud, latitud)
// });

layer.elevationInfo = {
  mode: "relative-to-ground",
  offset: 50,
  unit: "meters"
}

  // Cargar la capa COMARCAS
  var featureLayer = new FeatureLayer({
      url: "url_to_layer", // Sorry but it is private
      outFields: ["*"]
  });




  featureLayer.when(function() {
    console.log("Capa cargada correctamente:");
}, function(error) {
    console.error("Error al cargar la capa.", error);
});

  map.add(featureLayer);

  // Cargar el CSV con los datos de simbología y fecha
  esriRequest("path_to_file", {  // Sorry again but it is private
      responseType: "text"
  }).then(function(response) {


        console.log("CSV cargado con éxito."); // Verifica si el CSV fue cargado
        const csvData = parseCSV(response.data); // Parsear el CSV

        // Crear y configurar el TimeSlider
        var timeSlider = new TimeSlider({
            container: "timeSliderDiv",
            view: view,
            mode: "instant", // Selecciona una fecha a la vez
            fullTimeExtent: {
                start: new Date(2020, 11, 28), //OJO QUE LOS MESES VAN DE 0 A 11
                end: new Date(2023, 11, 31)
            },
            stops: {
                interval: {
                    value: 7,
                    unit: "days"
                }
            }
        });

        view.ui.add(timeSlider, "bottom-left");

        // Vincular el cambio de fecha del TimeSlider con la capa
        timeSlider.watch("timeExtent", function(timeExtent) {
            const selectedDate = timeSlider.timeExtent.end;


            // Filtrar el CSV para obtener los elementos correspondientes a la fecha seleccionada
            const filteredData = csvData.filter(row => {
                return new Date(row.fecha).toDateString() === selectedDate.toDateString();
            });



            // Si hay datos correspondientes a esa fecha, actualizar simbología
            if (filteredData.length > 0) {

                updateLayerSymbology(filteredData);
            } else {
                console.log("No se encontraron datos para la fecha seleccionada.");
            }
        });

// Función para actualizar la simbología en la capa
function updateLayerSymbology(data) {
  const uniqueValues = data.map(function(element) {

      return {
          value: element.comarca_sg,  // Asumimos que "id" es el campo que relaciona los elementos del CSV con los polígonos en la capa
          symbol: {
              type: "polygon-3d",  // Tipo de símbolo para polígonos 3D
              symbolLayers: [{
                  type: "extrude",
                  size: 5,
                  material: {color: getColorBasedOnAlert(element.alerta)},  // Asignar el color según la alerta
                  outline: { color: "black" }
              }]
          }
      };
  });


console.log("Valores únicos aplicados a los polígonos:", uniqueValues);



  const renderer = {

    type: "uniqueValue",
    field: "comarca_sg",
    uniqueValueInfos: uniqueValues,

};

  // Asignar el renderer a la capa
  featureLayer.renderer = renderer;
}


        // Función para obtener el color basado en el valor de alerta
        function getColorBasedOnAlert(alerta) {
          alerta = alerta.trim();
             // Verificar el valor de alerta
          if (alerta === "A5") {
              return "#d73027"; // Rojo oscuro
          } else if (alerta === "A4") {
              return "#fc8d59"; // Rojo claro
          } else if (alerta === "A3") {
              return "#fee08b"; // Amarillo
          } else if (alerta === "A2") {
              return "#d9ef8b"; // Amarillo verdoso
          } else if (alerta === "A1") {
              return "#91cf60"; // Verde claro
          } else if (alerta === "A0" || alerta === "NO ALERTA") {
              return "#1a9850"; // Verde intenso
          } else {
              return "#1a9850"; // Verde por defecto para valores desconocidos
          }
        }

        // Función para parsear el CSV
        function parseCSV(csvText) {
          const rows = csvText.split("n").map(row => row.trim()); // Eliminar espacios innecesarios
          const headers = rows[0].split(";").map(header => header.trim()); // Obtener los encabezados y eliminar espacios



          // Mapear los encabezados a los índices que necesitamos
          const indexId = headers.indexOf("comarca_sg");
          const indexFecha = headers.indexOf("date");
          const indexAlerta = headers.indexOf("riesgo");

          return rows.slice(1).map(row => {
              const columns = row.split(";").map(item => item.trim()); // Dividir por punto y coma
              return {
                  comarca_sg: columns[indexId],
                  fecha: new Date(columns[indexFecha]),
                  alerta: columns[indexAlerta]
              };
          });
      }


    }).catch(function(error) {
        console.error("Error al cargar el archivo CSV:", error); // Mostrar error en caso de que el CSV no se cargue
    });


  }); // LLAVES DEL FIN DEL CODIGO

Questions:

  1. Is there anything different I should consider when applying a UniqueValueRenderer in a SceneView compared to a MapView?

  2. Could there be a limitation or difference in how renderers are applied in 3D?

  3. I’m sure there is an error in the code that prevents the layer from displaying, but I can’t locate it.

I would appreciate any advice or suggestions on how to solve this problem. Thanks in advance!

What I’ve tried:

• Verified that the alert values are passed correctly using console.log().
• Tried removing the defaultSymbol to ensure it wasn’t overriding the renderer.
• Ensured that the comarca_sg field is correctly aligned between the CSV and the layer.
• I placed the layer in a scene view in AGOL, and it displays without issues, allowing me to visualize unique colors for unique values.