Search in sources :

Example 1 with LeafletPolygon

use of de.symeda.sormas.ui.map.LeafletPolygon in project SORMAS-Project by hzi-braunschweig.

the class DashboardMapComponent method showRegionsShapes.

private void showRegionsShapes(CaseMeasure caseMeasure, Date fromDate, Date toDate, Disease disease) {
    clearRegionShapes();
    map.setTileLayerOpacity(0.5f);
    List<RegionReferenceDto> regions = FacadeProvider.getRegionFacade().getAllActiveByServerCountry();
    List<LeafletPolygon> regionPolygons = new ArrayList<LeafletPolygon>();
    // draw outlines of all regions
    for (RegionReferenceDto region : regions) {
        GeoLatLon[][] regionShape = FacadeProvider.getGeoShapeProvider().getRegionShape(region);
        if (regionShape == null) {
            continue;
        }
        for (GeoLatLon[] regionShapePart : regionShape) {
            LeafletPolygon polygon = new LeafletPolygon();
            polygon.setCaption(region.getCaption());
            // fillOpacity is used, so we can still hover the region
            polygon.setOptions("{\"weight\": 1, \"color\": '#444', \"fillOpacity\": 0.02}");
            polygon.setLatLons(regionShapePart);
            regionPolygons.add(polygon);
            polygonRegions.add(region);
        }
    }
    map.addPolygonGroup(REGIONS_GROUP_ID, regionPolygons);
    List<Pair<DistrictDto, BigDecimal>> measurePerDistrict = FacadeProvider.getCaseFacade().getCaseMeasurePerDistrict(fromDate, toDate, disease, caseMeasure);
    if (caseMeasure == CaseMeasure.CASE_COUNT) {
        districtValuesLowerQuartile = measurePerDistrict.size() > 0 ? measurePerDistrict.get((int) (measurePerDistrict.size() * 0.25)).getElement1() : null;
        districtValuesMedian = measurePerDistrict.size() > 0 ? measurePerDistrict.get((int) (measurePerDistrict.size() * 0.5)).getElement1() : null;
        districtValuesUpperQuartile = measurePerDistrict.size() > 0 ? measurePerDistrict.get((int) (measurePerDistrict.size() * 0.75)).getElement1() : null;
    } else {
        // For case incidence, districts without or with a population <= 0 should not be
        // used for the calculation of the quartiles because they will falsify the
        // result
        List<Pair<DistrictDto, BigDecimal>> measurePerDistrictWithoutMissingPopulations = new ArrayList<>();
        measurePerDistrictWithoutMissingPopulations.addAll(measurePerDistrict);
        measurePerDistrictWithoutMissingPopulations.removeIf(d -> d.getElement1() == null || d.getElement1().intValue() <= 0);
        districtValuesLowerQuartile = measurePerDistrictWithoutMissingPopulations.size() > 0 ? measurePerDistrictWithoutMissingPopulations.get((int) (measurePerDistrictWithoutMissingPopulations.size() * 0.25)).getElement1() : null;
        districtValuesMedian = measurePerDistrictWithoutMissingPopulations.size() > 0 ? measurePerDistrictWithoutMissingPopulations.get((int) (measurePerDistrictWithoutMissingPopulations.size() * 0.5)).getElement1() : null;
        districtValuesUpperQuartile = measurePerDistrictWithoutMissingPopulations.size() > 0 ? measurePerDistrictWithoutMissingPopulations.get((int) (measurePerDistrictWithoutMissingPopulations.size() * 0.75)).getElement1() : null;
    }
    List<LeafletPolygon> districtPolygons = new ArrayList<LeafletPolygon>();
    // Draw relevant district fills
    for (Pair<DistrictDto, BigDecimal> districtMeasure : measurePerDistrict) {
        DistrictDto district = districtMeasure.getElement0();
        DistrictReferenceDto districtRef = district.toReference();
        BigDecimal districtValue = districtMeasure.getElement1();
        GeoLatLon[][] districtShape = FacadeProvider.getGeoShapeProvider().getDistrictShape(districtRef);
        if (districtShape == null) {
            continue;
        }
        String fillColor;
        if (districtValue.compareTo(BigDecimal.ZERO) == 0) {
            fillColor = "#000";
        } else if (districtValue.compareTo(districtValuesLowerQuartile) < 0) {
            fillColor = "#FEDD6C";
        } else if (districtValue.compareTo(districtValuesMedian) < 0) {
            fillColor = "#FDBF44";
        } else if (districtValue.compareTo(districtValuesUpperQuartile) < 0) {
            fillColor = "#F47B20";
        } else {
            fillColor = "#ED1B24";
        }
        if (caseMeasure == CaseMeasure.CASE_INCIDENCE) {
            if (districtValue == null || districtValue.intValue() <= 0) {
                // grey when region has no population data
                emptyPopulationDistrictPresent = true;
                fillColor = "#999";
            }
        }
        for (GeoLatLon[] districtShapePart : districtShape) {
            LeafletPolygon polygon = new LeafletPolygon();
            polygon.setCaption(district.getName() + "<br>" + districtValue);
            polygon.setOptions("{\"stroke\": false, \"color\": '" + fillColor + "', \"fillOpacity\": 0.8}");
            polygon.setLatLons(districtShapePart);
            districtPolygons.add(polygon);
            polygonDistricts.add(districtRef);
        }
    }
    map.addPolygonGroup(DISTRICTS_GROUP_ID, districtPolygons);
}
Also used : ArrayList(java.util.ArrayList) DistrictReferenceDto(de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto) BigDecimal(java.math.BigDecimal) DistrictDto(de.symeda.sormas.api.infrastructure.district.DistrictDto) RegionReferenceDto(de.symeda.sormas.api.infrastructure.region.RegionReferenceDto) LeafletPolygon(de.symeda.sormas.ui.map.LeafletPolygon) GeoLatLon(de.symeda.sormas.api.geo.GeoLatLon) Pair(de.symeda.sormas.api.utils.DataHelper.Pair)

Example 2 with LeafletPolygon

use of de.symeda.sormas.ui.map.LeafletPolygon in project SORMAS-Project by hzi-braunschweig.

the class StatisticsView method generateMap.

public void generateMap() {
    List<StatisticsCaseCountDto> resultData = generateStatistics();
    if (resultData.isEmpty()) {
        resultsLayout.addComponent(emptyResultLabel);
        return;
    }
    if (showCaseIncidence && caseIncidencePossible && populationReferenceYear != null && populationReferenceYear != Calendar.getInstance().get(Calendar.YEAR)) {
        referenceYearLabel = new Label(VaadinIcons.INFO_CIRCLE.getHtml() + " " + String.format(I18nProperties.getString(Strings.infoPopulationReferenceYear), populationReferenceYear), ContentMode.HTML);
        resultsLayout.addComponent(referenceYearLabel);
        CssStyles.style(referenceYearLabel, CssStyles.VSPACE_TOP_4);
    }
    if (showCaseIncidence && (!caseIncidencePossible || hasMissingPopulationData)) {
        if (!caseIncidencePossible) {
            if (hasMissingPopulationData) {
                caseIncidenceNotPossibleLabel = new Label(VaadinIcons.INFO_CIRCLE.getHtml() + " " + String.format(I18nProperties.getString(Strings.infoCaseIncidenceNotPossible), missingPopulationDataNames), ContentMode.HTML);
            } else {
                caseIncidenceNotPossibleLabel = new Label(VaadinIcons.INFO_CIRCLE.getHtml() + " " + I18nProperties.getString(Strings.infoCaseIncidenceIncompatible), ContentMode.HTML);
            }
        } else {
            caseIncidenceNotPossibleLabel = new Label(VaadinIcons.INFO_CIRCLE.getHtml() + " " + String.format(I18nProperties.getString(Strings.infoCaseIncidenceMissingPopulationData), missingPopulationDataNames), ContentMode.HTML);
        }
        resultsLayout.addComponent(caseIncidenceNotPossibleLabel);
        caseIncidenceNotPossibleLabel.setWidth(100, Unit.PERCENTAGE);
        CssStyles.style(caseIncidenceNotPossibleLabel, CssStyles.VSPACE_TOP_4);
    }
    HorizontalLayout mapLayout = new HorizontalLayout();
    mapLayout.setSpacing(true);
    mapLayout.setMargin(false);
    mapLayout.setWidth(100, Unit.PERCENTAGE);
    mapLayout.setHeightUndefined();
    LeafletMap map = new LeafletMap();
    map.setTileLayerOpacity(0.5f);
    map.setWidth(100, Unit.PERCENTAGE);
    map.setHeight(580, Unit.PIXELS);
    map.setZoom(FacadeProvider.getConfigFacade().getMapZoom());
    GeoLatLon mapCenter = FacadeProvider.getGeoShapeProvider().getCenterOfAllRegions();
    if (mapCenter != null) {
        map.setCenter(mapCenter);
    } else {
        GeoLatLon countryCenter = FacadeProvider.getConfigFacade().getCountryCenter();
        map.setCenter(countryCenter);
    }
    if (cbHideOtherCountries.getValue()) {
        LeafletMapUtil.addOtherCountriesOverlay(map);
    }
    List<RegionReferenceDto> regions = FacadeProvider.getRegionFacade().getAllActiveByServerCountry();
    List<LeafletPolygon> outlinePolygones = new ArrayList<>();
    // draw outlines of all regions
    for (RegionReferenceDto region : regions) {
        GeoLatLon[][] regionShape = FacadeProvider.getGeoShapeProvider().getRegionShape(region);
        if (regionShape == null) {
            continue;
        }
        // fillOpacity is used, so we can still hover the region
        Arrays.stream(regionShape).forEach(regionShapePart -> {
            LeafletPolygon polygon = new LeafletPolygon();
            polygon.setCaption(region.getCaption());
            polygon.setOptions("{\"weight\": 1, \"color\": '#888', \"fillOpacity\": 0.02}");
            polygon.setLatLons(regionShapePart);
            outlinePolygones.add(polygon);
        });
    }
    map.addPolygonGroup("outlines", outlinePolygones);
    if (!showCaseIncidence || !caseIncidencePossible) {
        resultData.sort(Comparator.comparingInt(StatisticsCaseCountDto::getCaseCount));
    } else {
        resultData.sort((a, b) -> {
            BigDecimal incidenceA = a.getIncidence(incidenceDivisor);
            BigDecimal incidenceB = b.getIncidence(incidenceDivisor);
            return DataHelper.compare(incidenceA, incidenceB);
        });
    }
    BigDecimal valuesLowerQuartile, valuesMedian, valuesUpperQuartile;
    if (!showCaseIncidence || !caseIncidencePossible) {
        valuesLowerQuartile = resultData.size() > 0 ? new BigDecimal(resultData.get((int) (resultData.size() * 0.25)).getCaseCount()) : BigDecimal.ZERO;
        valuesMedian = resultData.size() > 0 ? new BigDecimal(resultData.get((int) (resultData.size() * 0.5)).getCaseCount()) : BigDecimal.ZERO;
        valuesUpperQuartile = resultData.size() > 0 ? new BigDecimal(resultData.get((int) (resultData.size() * 0.75)).getCaseCount()) : BigDecimal.ZERO;
    } else {
        valuesLowerQuartile = resultData.size() > 0 ? resultData.get((int) (resultData.size() * 0.25)).getIncidence(incidenceDivisor) : BigDecimal.ZERO;
        if (valuesLowerQuartile == null) {
            valuesLowerQuartile = BigDecimal.ZERO;
        }
        valuesMedian = resultData.size() > 0 ? resultData.get((int) (resultData.size() * 0.5)).getIncidence(incidenceDivisor) : BigDecimal.ZERO;
        if (valuesMedian == null) {
            valuesMedian = BigDecimal.ZERO;
        }
        valuesUpperQuartile = resultData.size() > 0 ? resultData.get((int) (resultData.size() * 0.75)).getIncidence(incidenceDivisor) : BigDecimal.ZERO;
        if (valuesUpperQuartile == null) {
            valuesUpperQuartile = BigDecimal.ZERO;
        }
    }
    List<LeafletPolygon> resultPolygons = new ArrayList<LeafletPolygon>();
    boolean hasNullValue = false;
    // Draw relevant district fills
    for (StatisticsCaseCountDto resultRow : resultData) {
        ReferenceDto regionOrDistrict = (ReferenceDto) resultRow.getRowKey();
        String shapeUuid = regionOrDistrict.getUuid();
        BigDecimal regionOrDistrictValue;
        if (!showCaseIncidence || !caseIncidencePossible) {
            regionOrDistrictValue = new BigDecimal(resultRow.getCaseCount());
        } else {
            regionOrDistrictValue = resultRow.getIncidence(incidenceDivisor);
        }
        hasNullValue |= regionOrDistrictValue == null;
        GeoLatLon[][] shape;
        switch(visualizationComponent.getVisualizationMapType()) {
            case REGIONS:
                shape = FacadeProvider.getGeoShapeProvider().getRegionShape(new RegionReferenceDto(shapeUuid, null, null));
                break;
            case DISTRICTS:
                shape = FacadeProvider.getGeoShapeProvider().getDistrictShape(new DistrictReferenceDto(shapeUuid, null, null));
                break;
            default:
                throw new IllegalArgumentException(visualizationComponent.getVisualizationMapType().toString());
        }
        if (shape == null) {
            continue;
        }
        for (int part = 0; part < shape.length; part++) {
            GeoLatLon[] shapePart = shape[part];
            String fillColor;
            String fillOpacity = "0.8";
            if (regionOrDistrictValue == null) {
                fillColor = "#888";
            } else if (regionOrDistrictValue.compareTo(BigDecimal.ZERO) == 0) {
                fillColor = "#000";
                fillOpacity = "0";
            } else if (regionOrDistrictValue.compareTo(valuesLowerQuartile) < 0) {
                fillColor = "#FEDD6C";
            } else if (regionOrDistrictValue.compareTo(valuesMedian) < 0) {
                fillColor = "#FDBF44";
            } else if (regionOrDistrictValue.compareTo(valuesUpperQuartile) < 0) {
                fillColor = "#F47B20";
            } else {
                fillColor = "#ED1B24";
            }
            LeafletPolygon polygon = new LeafletPolygon();
            if (regionOrDistrictValue == null) {
                polygon.setCaption(regionOrDistrict.getCaption() + "<br>" + I18nProperties.getCaption(Captions.notAvailableShort));
            } else {
                polygon.setCaption(regionOrDistrict.getCaption() + "<br>" + regionOrDistrictValue);
            }
            // fillOpacity is used, so we can still hover the region
            polygon.setOptions("{\"stroke\": true, \"color\": '#000000', \"weight\": 1, \"fillColor\": '" + fillColor + "', \"fillOpacity\": " + fillOpacity + "}");
            polygon.setLatLons(shapePart);
            resultPolygons.add(polygon);
        }
    }
    // sort polygon array, so that polygons which are completely contained by another appear on top
    List<Integer[]> indexesToSwap = new ArrayList<>();
    for (int poly1index = 0; poly1index < resultPolygons.size(); poly1index++) {
        LeafletPolygon poly1 = resultPolygons.get(poly1index);
        for (int poly2index = poly1index; poly2index < resultPolygons.size(); poly2index++) {
            LeafletPolygon poly2 = resultPolygons.get(poly2index);
            if (poly1index == poly2index) {
                continue;
            }
            // if the max/min values of poly1 are completely inside those of poly2, switch both
            if (poly1.getMaxLatLon()[0] < poly2.getMaxLatLon()[0] && poly1.getMinLatLon()[0] > poly2.getMinLatLon()[0] && poly1.getMaxLatLon()[1] < poly2.getMaxLatLon()[1] && poly1.getMinLatLon()[1] > poly2.getMinLatLon()[1]) {
                // make sure not to change the list we are currently iterating over
                indexesToSwap.add(new Integer[] { poly1index, poly2index });
            }
        }
    }
    for (Integer[] swaps : indexesToSwap) {
        Collections.swap(resultPolygons, swaps[0], swaps[1]);
    }
    map.addPolygonGroup("results", resultPolygons);
    mapLayout.addComponent(map);
    mapLayout.setExpandRatio(map, 1);
    if (showCaseIncidence && caseIncidencePossible) {
        valuesLowerQuartile = valuesLowerQuartile.setScale(2, RoundingMode.HALF_UP);
        valuesMedian = valuesMedian.setScale(2, RoundingMode.HALF_UP);
        valuesUpperQuartile = valuesUpperQuartile.setScale(2, RoundingMode.HALF_UP);
    }
    AbstractOrderedLayout regionLegend = DashboardMapComponent.buildRegionLegend(true, showCaseIncidence && caseIncidencePossible ? CaseMeasure.CASE_INCIDENCE : CaseMeasure.CASE_COUNT, hasNullValue, valuesLowerQuartile, valuesMedian, valuesUpperQuartile, incidenceDivisor);
    Label legendHeader = new Label(I18nProperties.getCaption(Captions.dashboardMapKey));
    CssStyles.style(legendHeader, CssStyles.H4, CssStyles.VSPACE_4, CssStyles.VSPACE_TOP_NONE);
    regionLegend.addComponent(legendHeader, 0);
    mapLayout.addComponent(regionLegend);
    mapLayout.setExpandRatio(regionLegend, 0);
    resultsLayout.addComponent(mapLayout);
    resultsLayout.setExpandRatio(mapLayout, 1);
    if (showCaseIncidence && hasMissingPopulationData && caseIncidencePossible) {
        resultsLayout.addComponent(caseIncidenceNotPossibleLabel);
    }
}
Also used : ReferenceDto(de.symeda.sormas.api.ReferenceDto) CommunityReferenceDto(de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto) RegionReferenceDto(de.symeda.sormas.api.infrastructure.region.RegionReferenceDto) DistrictReferenceDto(de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto) FacilityReferenceDto(de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto) Label(com.vaadin.ui.Label) ArrayList(java.util.ArrayList) DistrictReferenceDto(de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto) BigDecimal(java.math.BigDecimal) HorizontalLayout(com.vaadin.ui.HorizontalLayout) RegionReferenceDto(de.symeda.sormas.api.infrastructure.region.RegionReferenceDto) LeafletMap(de.symeda.sormas.ui.map.LeafletMap) StatisticsCaseCountDto(de.symeda.sormas.api.statistics.StatisticsCaseCountDto) LeafletPolygon(de.symeda.sormas.ui.map.LeafletPolygon) AbstractOrderedLayout(com.vaadin.ui.AbstractOrderedLayout) GeoLatLon(de.symeda.sormas.api.geo.GeoLatLon)

Aggregations

GeoLatLon (de.symeda.sormas.api.geo.GeoLatLon)2 DistrictReferenceDto (de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto)2 RegionReferenceDto (de.symeda.sormas.api.infrastructure.region.RegionReferenceDto)2 LeafletPolygon (de.symeda.sormas.ui.map.LeafletPolygon)2 BigDecimal (java.math.BigDecimal)2 ArrayList (java.util.ArrayList)2 AbstractOrderedLayout (com.vaadin.ui.AbstractOrderedLayout)1 HorizontalLayout (com.vaadin.ui.HorizontalLayout)1 Label (com.vaadin.ui.Label)1 ReferenceDto (de.symeda.sormas.api.ReferenceDto)1 CommunityReferenceDto (de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto)1 DistrictDto (de.symeda.sormas.api.infrastructure.district.DistrictDto)1 FacilityReferenceDto (de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto)1 StatisticsCaseCountDto (de.symeda.sormas.api.statistics.StatisticsCaseCountDto)1 Pair (de.symeda.sormas.api.utils.DataHelper.Pair)1 LeafletMap (de.symeda.sormas.ui.map.LeafletMap)1