diff --git a/src/lib/marble/geodata/data/GeoDataFeature.h b/src/lib/marble/geodata/data/GeoDataFeature.h --- a/src/lib/marble/geodata/data/GeoDataFeature.h +++ b/src/lib/marble/geodata/data/GeoDataFeature.h @@ -629,6 +629,8 @@ static QSharedPointer presetStyle( GeoDataVisualCategory category ); + static QString visualCategoryName(GeoDataVisualCategory category); + virtual void detach(); protected: diff --git a/src/lib/marble/geodata/data/GeoDataFeature.cpp b/src/lib/marble/geodata/data/GeoDataFeature.cpp --- a/src/lib/marble/geodata/data/GeoDataFeature.cpp +++ b/src/lib/marble/geodata/data/GeoDataFeature.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "MarbleDirs.h" #include "MarbleDebug.h" @@ -675,6 +676,282 @@ return GeoDataFeaturePrivate::s_defaultStyle[ category ]; } +QString GeoDataFeature::visualCategoryName(GeoDataFeature::GeoDataVisualCategory category) +{ + static QHash s_visualCategoryNames; + if (s_visualCategoryNames.isEmpty()) { + s_visualCategoryNames[None] = "None"; + s_visualCategoryNames[Default] = "Default"; + s_visualCategoryNames[Unknown] = "Unknown"; + s_visualCategoryNames[SmallCity] = "SmallCity"; + s_visualCategoryNames[SmallCountyCapital] = "SmallCountyCapital"; + s_visualCategoryNames[SmallStateCapital] = "SmallStateCapital"; + s_visualCategoryNames[SmallNationCapital] = "SmallNationCapital"; + s_visualCategoryNames[MediumCity] = "MediumCity"; + s_visualCategoryNames[MediumCountyCapital] = "MediumCountyCapital"; + s_visualCategoryNames[MediumStateCapital] = "MediumStateCapital"; + s_visualCategoryNames[MediumNationCapital] = "MediumNationCapital"; + s_visualCategoryNames[BigCity] = "BigCity"; + s_visualCategoryNames[BigCountyCapital] = "BigCountyCapital"; + s_visualCategoryNames[BigStateCapital] = "BigStateCapital"; + s_visualCategoryNames[BigNationCapital] = "BigNationCapital"; + s_visualCategoryNames[LargeCity] = "LargeCity"; + s_visualCategoryNames[LargeCountyCapital] = "LargeCountyCapital"; + s_visualCategoryNames[LargeStateCapital] = "LargeStateCapital"; + s_visualCategoryNames[LargeNationCapital] = "LargeNationCapital"; + s_visualCategoryNames[Nation] = "Nation"; + s_visualCategoryNames[PlaceCity] = "PlaceCity"; + s_visualCategoryNames[PlaceSuburb] = "PlaceSuburb"; + s_visualCategoryNames[PlaceHamlet] = "PlaceHamlet"; + s_visualCategoryNames[PlaceLocality] = "PlaceLocality"; + s_visualCategoryNames[PlaceTown] = "PlaceTown"; + s_visualCategoryNames[PlaceVillage] = "PlaceVillage"; + s_visualCategoryNames[Mountain] = "Mountain"; + s_visualCategoryNames[Volcano] = "Volcano"; + s_visualCategoryNames[Mons] = "Mons"; + s_visualCategoryNames[Valley] = "Valley"; + s_visualCategoryNames[Continent] = "Continent"; + s_visualCategoryNames[Ocean] = "Ocean"; + s_visualCategoryNames[OtherTerrain] = "OtherTerrain"; + s_visualCategoryNames[Crater] = "Crater"; + s_visualCategoryNames[Mare] = "Mare"; + s_visualCategoryNames[GeographicPole] = "GeographicPole"; + s_visualCategoryNames[MagneticPole] = "MagneticPole"; + s_visualCategoryNames[ShipWreck] = "ShipWreck"; + s_visualCategoryNames[AirPort] = "AirPort"; + s_visualCategoryNames[Observatory] = "Observatory"; + s_visualCategoryNames[MilitaryDangerArea] = "MilitaryDangerArea"; + s_visualCategoryNames[Wikipedia] = "Wikipedia"; + s_visualCategoryNames[OsmSite] = "OsmSite"; + s_visualCategoryNames[Coordinate] = "Coordinate"; + s_visualCategoryNames[MannedLandingSite] = "MannedLandingSite"; + s_visualCategoryNames[RoboticRover] = "RoboticRover"; + s_visualCategoryNames[UnmannedSoftLandingSite] = "UnmannedSoftLandingSite"; + s_visualCategoryNames[UnmannedHardLandingSite] = "UnmannedHardLandingSite"; + s_visualCategoryNames[Folder] = "Folder"; + s_visualCategoryNames[Bookmark] = "Bookmark"; + s_visualCategoryNames[NaturalWater] = "NaturalWater"; + s_visualCategoryNames[NaturalWood] = "NaturalWood"; + s_visualCategoryNames[NaturalBeach] = "NaturalBeach"; + s_visualCategoryNames[NaturalWetland] = "NaturalWetland"; + s_visualCategoryNames[NaturalGlacier] = "NaturalGlacier"; + s_visualCategoryNames[NaturalScrub] = "NaturalScrub"; + s_visualCategoryNames[NaturalCliff] = "NaturalCliff"; + s_visualCategoryNames[NaturalHeath] = "NaturalHeath"; + s_visualCategoryNames[HighwayTrafficSignals] = "HighwayTrafficSignals"; + s_visualCategoryNames[HighwaySteps] = "HighwaySteps"; + s_visualCategoryNames[HighwayUnknown] = "HighwayUnknown"; + s_visualCategoryNames[HighwayPath] = "HighwayPath"; + s_visualCategoryNames[HighwayFootway] = "HighwayFootway"; + s_visualCategoryNames[HighwayTrack] = "HighwayTrack"; + s_visualCategoryNames[HighwayPedestrian] = "HighwayPedestrian"; + s_visualCategoryNames[HighwayCycleway] = "HighwayCycleway"; + s_visualCategoryNames[HighwayService] = "HighwayService"; + s_visualCategoryNames[HighwayRoad] = "HighwayRoad"; + s_visualCategoryNames[HighwayResidential] = "HighwayResidential"; + s_visualCategoryNames[HighwayLivingStreet] = "HighwayLivingStreet"; + s_visualCategoryNames[HighwayUnclassified] = "HighwayUnclassified"; + s_visualCategoryNames[HighwayTertiaryLink] = "HighwayTertiaryLink"; + s_visualCategoryNames[HighwayTertiary] = "HighwayTertiary"; + s_visualCategoryNames[HighwaySecondaryLink] = "HighwaySecondaryLink"; + s_visualCategoryNames[HighwaySecondary] = "HighwaySecondary"; + s_visualCategoryNames[HighwayPrimaryLink] = "HighwayPrimaryLink"; + s_visualCategoryNames[HighwayPrimary] = "HighwayPrimary"; + s_visualCategoryNames[HighwayTrunkLink] = "HighwayTrunkLink"; + s_visualCategoryNames[HighwayTrunk] = "HighwayTrunk"; + s_visualCategoryNames[HighwayMotorwayLink] = "HighwayMotorwayLink"; + s_visualCategoryNames[HighwayMotorway] = "HighwayMotorway"; + s_visualCategoryNames[Building] = "Building"; + s_visualCategoryNames[AccomodationCamping] = "AccomodationCamping"; + s_visualCategoryNames[AccomodationHostel] = "AccomodationHostel"; + s_visualCategoryNames[AccomodationHotel] = "AccomodationHotel"; + s_visualCategoryNames[AccomodationMotel] = "AccomodationMotel"; + s_visualCategoryNames[AccomodationYouthHostel] = "AccomodationYouthHostel"; + s_visualCategoryNames[AccomodationGuestHouse] = "AccomodationGuestHouse"; + s_visualCategoryNames[AmenityLibrary] = "AmenityLibrary"; + s_visualCategoryNames[EducationCollege] = "EducationCollege"; + s_visualCategoryNames[EducationSchool] = "EducationSchool"; + s_visualCategoryNames[EducationUniversity] = "EducationUniversity"; + s_visualCategoryNames[FoodBar] = "FoodBar"; + s_visualCategoryNames[FoodBiergarten] = "FoodBiergarten"; + s_visualCategoryNames[FoodCafe] = "FoodCafe"; + s_visualCategoryNames[FoodFastFood] = "FoodFastFood"; + s_visualCategoryNames[FoodPub] = "FoodPub"; + s_visualCategoryNames[FoodRestaurant] = "FoodRestaurant"; + s_visualCategoryNames[HealthDentist] = "HealthDentist"; + s_visualCategoryNames[HealthDoctors] = "HealthDoctors"; + s_visualCategoryNames[HealthHospital] = "HealthHospital"; + s_visualCategoryNames[HealthPharmacy] = "HealthPharmacy"; + s_visualCategoryNames[HealthVeterinary] = "HealthVeterinary"; + s_visualCategoryNames[MoneyAtm] = "MoneyAtm"; + s_visualCategoryNames[MoneyBank] = "MoneyBank"; + s_visualCategoryNames[AmenityArchaeologicalSite] = "AmenityArchaeologicalSite"; + s_visualCategoryNames[AmenityEmbassy] = "AmenityEmbassy"; + s_visualCategoryNames[AmenityEmergencyPhone] = "AmenityEmergencyPhone"; + s_visualCategoryNames[AmenityWaterPark] = "AmenityWaterPark"; + s_visualCategoryNames[AmenityCommunityCentre] = "AmenityCommunityCentre"; + s_visualCategoryNames[AmenityFountain] = "AmenityFountain"; + s_visualCategoryNames[AmenityNightClub] = "AmenityNightClub"; + s_visualCategoryNames[AmenityBench] = "AmenityBench"; + s_visualCategoryNames[AmenityCourtHouse] = "AmenityCourtHouse"; + s_visualCategoryNames[AmenityFireStation] = "AmenityFireStation"; + s_visualCategoryNames[AmenityHuntingStand] = "AmenityHuntingStand"; + s_visualCategoryNames[AmenityPolice] = "AmenityPolice"; + s_visualCategoryNames[AmenityPostBox] = "AmenityPostBox"; + s_visualCategoryNames[AmenityPostOffice] = "AmenityPostOffice"; + s_visualCategoryNames[AmenityPrison] = "AmenityPrison"; + s_visualCategoryNames[AmenityRecycling] = "AmenityRecycling"; + s_visualCategoryNames[AmenityTelephone] = "AmenityTelephone"; + s_visualCategoryNames[AmenityToilets] = "AmenityToilets"; + s_visualCategoryNames[AmenityTownHall] = "AmenityTownHall"; + s_visualCategoryNames[AmenityWasteBasket] = "AmenityWasteBasket"; + s_visualCategoryNames[AmenityDrinkingWater] = "AmenityDrinkingWater"; + s_visualCategoryNames[AmenityGraveyard] = "AmenityGraveyard"; + s_visualCategoryNames[BarrierCityWall] = "BarrierCityWall"; + s_visualCategoryNames[BarrierGate] = "BarrierGate"; + s_visualCategoryNames[BarrierLiftGate] = "BarrierLiftGate"; + s_visualCategoryNames[BarrierWall] = "BarrierWall"; + s_visualCategoryNames[NaturalPeak] = "NaturalPeak"; + s_visualCategoryNames[NaturalTree] = "NaturalTree"; + s_visualCategoryNames[ShopBeverages] = "ShopBeverages"; + s_visualCategoryNames[ShopHifi] = "ShopHifi"; + s_visualCategoryNames[ShopSupermarket] = "ShopSupermarket"; + s_visualCategoryNames[ShopAlcohol] = "ShopAlcohol"; + s_visualCategoryNames[ShopBakery] = "ShopBakery"; + s_visualCategoryNames[ShopButcher] = "ShopButcher"; + s_visualCategoryNames[ShopConfectionery] = "ShopConfectionery"; + s_visualCategoryNames[ShopConvenience] = "ShopConvenience"; + s_visualCategoryNames[ShopGreengrocer] = "ShopGreengrocer"; + s_visualCategoryNames[ShopSeafood] = "ShopSeafood"; + s_visualCategoryNames[ShopDepartmentStore] = "ShopDepartmentStore"; + s_visualCategoryNames[ShopKiosk] = "ShopKiosk"; + s_visualCategoryNames[ShopBag] = "ShopBag"; + s_visualCategoryNames[ShopClothes] = "ShopClothes"; + s_visualCategoryNames[ShopFashion] = "ShopFashion"; + s_visualCategoryNames[ShopJewelry] = "ShopJewelry"; + s_visualCategoryNames[ShopShoes] = "ShopShoes"; + s_visualCategoryNames[ShopVarietyStore] = "ShopVarietyStore"; + s_visualCategoryNames[ShopBeauty] = "ShopBeauty"; + s_visualCategoryNames[ShopChemist] = "ShopChemist"; + s_visualCategoryNames[ShopCosmetics] = "ShopCosmetics"; + s_visualCategoryNames[ShopHairdresser] = "ShopHairdresser"; + s_visualCategoryNames[ShopOptician] = "ShopOptician"; + s_visualCategoryNames[ShopPerfumery] = "ShopPerfumery"; + s_visualCategoryNames[ShopDoitYourself] = "ShopDoitYourself"; + s_visualCategoryNames[ShopFlorist] = "ShopFlorist"; + s_visualCategoryNames[ShopHardware] = "ShopHardware"; + s_visualCategoryNames[ShopFurniture] = "ShopFurniture"; + s_visualCategoryNames[ShopElectronics] = "ShopElectronics"; + s_visualCategoryNames[ShopMobilePhone] = "ShopMobilePhone"; + s_visualCategoryNames[ShopBicycle] = "ShopBicycle"; + s_visualCategoryNames[ShopCar] = "ShopCar"; + s_visualCategoryNames[ShopCarRepair] = "ShopCarRepair"; + s_visualCategoryNames[ShopCarParts] = "ShopCarParts"; + s_visualCategoryNames[ShopMotorcycle] = "ShopMotorcycle"; + s_visualCategoryNames[ShopOutdoor] = "ShopOutdoor"; + s_visualCategoryNames[ShopMusicalInstrument] = "ShopMusicalInstrument"; + s_visualCategoryNames[ShopPhoto] = "ShopPhoto"; + s_visualCategoryNames[ShopBook] = "ShopBook"; + s_visualCategoryNames[ShopGift] = "ShopGift"; + s_visualCategoryNames[ShopStationery] = "ShopStationery"; + s_visualCategoryNames[ShopLaundry] = "ShopLaundry"; + s_visualCategoryNames[ShopPet] = "ShopPet"; + s_visualCategoryNames[ShopToys] = "ShopToys"; + s_visualCategoryNames[ShopTravelAgency] = "ShopTravelAgency"; + s_visualCategoryNames[Shop] = "Shop"; + s_visualCategoryNames[ManmadeBridge] = "ManmadeBridge"; + s_visualCategoryNames[ManmadeLighthouse] = "ManmadeLighthouse"; + s_visualCategoryNames[ManmadePier] = "ManmadePier"; + s_visualCategoryNames[ManmadeWaterTower] = "ManmadeWaterTower"; + s_visualCategoryNames[ManmadeWindMill] = "ManmadeWindMill"; + s_visualCategoryNames[TouristAttraction] = "TouristAttraction"; + s_visualCategoryNames[TouristCastle] = "TouristCastle"; + s_visualCategoryNames[TouristCinema] = "TouristCinema"; + s_visualCategoryNames[TouristInformation] = "TouristInformation"; + s_visualCategoryNames[TouristMonument] = "TouristMonument"; + s_visualCategoryNames[TouristMuseum] = "TouristMuseum"; + s_visualCategoryNames[TouristRuin] = "TouristRuin"; + s_visualCategoryNames[TouristTheatre] = "TouristTheatre"; + s_visualCategoryNames[TouristThemePark] = "TouristThemePark"; + s_visualCategoryNames[TouristViewPoint] = "TouristViewPoint"; + s_visualCategoryNames[TouristZoo] = "TouristZoo"; + s_visualCategoryNames[TouristAlpineHut] = "TouristAlpineHut"; + s_visualCategoryNames[TransportAerodrome] = "TransportAerodrome"; + s_visualCategoryNames[TransportHelipad] = "TransportHelipad"; + s_visualCategoryNames[TransportAirportTerminal] = "TransportAirportTerminal"; + s_visualCategoryNames[TransportBusStation] = "TransportBusStation"; + s_visualCategoryNames[TransportBusStop] = "TransportBusStop"; + s_visualCategoryNames[TransportCarShare] = "TransportCarShare"; + s_visualCategoryNames[TransportFuel] = "TransportFuel"; + s_visualCategoryNames[TransportParking] = "TransportParking"; + s_visualCategoryNames[TransportParkingSpace] = "TransportParkingSpace"; + s_visualCategoryNames[TransportPlatform] = "TransportPlatform"; + s_visualCategoryNames[TransportRentalBicycle] = "TransportRentalBicycle"; + s_visualCategoryNames[TransportRentalCar] = "TransportRentalCar"; + s_visualCategoryNames[TransportTaxiRank] = "TransportTaxiRank"; + s_visualCategoryNames[TransportTrainStation] = "TransportTrainStation"; + s_visualCategoryNames[TransportTramStop] = "TransportTramStop"; + s_visualCategoryNames[TransportBicycleParking] = "TransportBicycleParking"; + s_visualCategoryNames[TransportMotorcycleParking] = "TransportMotorcycleParking"; + s_visualCategoryNames[TransportSubwayEntrance] = "TransportSubwayEntrance"; + s_visualCategoryNames[ReligionPlaceOfWorship] = "ReligionPlaceOfWorship"; + s_visualCategoryNames[ReligionBahai] = "ReligionBahai"; + s_visualCategoryNames[ReligionBuddhist] = "ReligionBuddhist"; + s_visualCategoryNames[ReligionChristian] = "ReligionChristian"; + s_visualCategoryNames[ReligionMuslim] = "ReligionMuslim"; + s_visualCategoryNames[ReligionHindu] = "ReligionHindu"; + s_visualCategoryNames[ReligionJain] = "ReligionJain"; + s_visualCategoryNames[ReligionJewish] = "ReligionJewish"; + s_visualCategoryNames[ReligionShinto] = "ReligionShinto"; + s_visualCategoryNames[ReligionSikh] = "ReligionSikh"; + s_visualCategoryNames[LeisureGolfCourse] = "LeisureGolfCourse"; + s_visualCategoryNames[LeisurePark] = "LeisurePark"; + s_visualCategoryNames[LeisurePlayground] = "LeisurePlayground"; + s_visualCategoryNames[LeisurePitch] = "LeisurePitch"; + s_visualCategoryNames[LeisureSportsCentre] = "LeisureSportsCentre"; + s_visualCategoryNames[LeisureStadium] = "LeisureStadium"; + s_visualCategoryNames[LeisureTrack] = "LeisureTrack"; + s_visualCategoryNames[LeisureSwimmingPool] = "LeisureSwimmingPool"; + s_visualCategoryNames[LanduseAllotments] = "LanduseAllotments"; + s_visualCategoryNames[LanduseBasin] = "LanduseBasin"; + s_visualCategoryNames[LanduseCemetery] = "LanduseCemetery"; + s_visualCategoryNames[LanduseCommercial] = "LanduseCommercial"; + s_visualCategoryNames[LanduseConstruction] = "LanduseConstruction"; + s_visualCategoryNames[LanduseFarmland] = "LanduseFarmland"; + s_visualCategoryNames[LanduseFarmyard] = "LanduseFarmyard"; + s_visualCategoryNames[LanduseGarages] = "LanduseGarages"; + s_visualCategoryNames[LanduseGrass] = "LanduseGrass"; + s_visualCategoryNames[LanduseIndustrial] = "LanduseIndustrial"; + s_visualCategoryNames[LanduseLandfill] = "LanduseLandfill"; + s_visualCategoryNames[LanduseMeadow] = "LanduseMeadow"; + s_visualCategoryNames[LanduseMilitary] = "LanduseMilitary"; + s_visualCategoryNames[LanduseQuarry] = "LanduseQuarry"; + s_visualCategoryNames[LanduseRailway] = "LanduseRailway"; + s_visualCategoryNames[LanduseReservoir] = "LanduseReservoir"; + s_visualCategoryNames[LanduseResidential] = "LanduseResidential"; + s_visualCategoryNames[LanduseRetail] = "LanduseRetail"; + s_visualCategoryNames[LanduseOrchard] = "LanduseOrchard"; + s_visualCategoryNames[LanduseVineyard] = "LanduseVineyard"; + s_visualCategoryNames[RailwayRail] = "RailwayRail"; + s_visualCategoryNames[RailwayNarrowGauge] = "RailwayNarrowGauge"; + s_visualCategoryNames[RailwayTram] = "RailwayTram"; + s_visualCategoryNames[RailwayLightRail] = "RailwayLightRail"; + s_visualCategoryNames[RailwayAbandoned] = "RailwayAbandoned"; + s_visualCategoryNames[RailwaySubway] = "RailwaySubway"; + s_visualCategoryNames[RailwayPreserved] = "RailwayPreserved"; + s_visualCategoryNames[RailwayMiniature] = "RailwayMiniature"; + s_visualCategoryNames[RailwayConstruction] = "RailwayConstruction"; + s_visualCategoryNames[RailwayMonorail] = "RailwayMonorail"; + s_visualCategoryNames[RailwayFunicular] = "RailwayFunicular"; + s_visualCategoryNames[PowerTower] = "PowerTower"; + s_visualCategoryNames[Satellite] = "Satellite"; + s_visualCategoryNames[LastIndex] = "LastIndex"; + } + + Q_ASSERT(s_visualCategoryNames.contains(category)); + return s_visualCategoryNames[category]; +} + QFont GeoDataFeature::defaultFont() { return GeoDataFeaturePrivate::s_defaultFont; diff --git a/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h b/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h --- a/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h +++ b/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.h @@ -29,13 +29,18 @@ virtual const GeoDataLatLonAltBox& latLonAltBox() const; - virtual void paint( GeoPainter* painter, const ViewportParams *viewport ); + + void paint(GeoPainter* painter, const ViewportParams *viewport, const QString &layer); protected: const GeoDataLineString *m_lineString; - static const float s_outlineZValue; - virtual void createDecorations(); +private: + void paintOutline(GeoPainter *painter, const ViewportParams *viewport); + void paintInline(GeoPainter *painter, const ViewportParams *viewport); + void paintLabel(GeoPainter *painter, const ViewportParams *viewport); + + QPen configurePainter(GeoPainter* painter, const ViewportParams *viewport, LabelPositionFlags &labelPositionFlags) const; }; } diff --git a/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp b/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp --- a/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp +++ b/src/lib/marble/geodata/graphicsitem/GeoLineStringGraphicsItem.cpp @@ -16,6 +16,7 @@ #include "GeoPainter.h" #include "ViewportParams.h" #include "GeoDataStyle.h" +#include "MarbleDebug.h" namespace Marble { @@ -25,43 +26,107 @@ : GeoGraphicsItem( feature ), m_lineString( lineString ) { + QString const category = GeoDataFeature::visualCategoryName(feature->visualCategory()); + QStringList paintLayers; + paintLayers << QString("LineString/%1/outline").arg(category); + paintLayers << QString("LineString/%1/inline").arg(category); + paintLayers << QString("LineString/%1/label").arg(category); + setPaintLayers(paintLayers); } -const float GeoLineStringGraphicsItem::s_outlineZValue = -0.001; +void GeoLineStringGraphicsItem::setLineString( const GeoDataLineString* lineString ) +{ + m_lineString = lineString; +} -void GeoLineStringGraphicsItem::createDecorations() +const GeoDataLatLonAltBox& GeoLineStringGraphicsItem::latLonAltBox() const { - if ( style() != nullptr ) { - if ( style()->lineStyle().cosmeticOutline() ) { - GeoLineStringGraphicsItem* outline = new GeoLineStringGraphicsItem(this->feature(), this->m_lineString); - outline->setZValue(this->zValue() + s_outlineZValue); + return m_lineString->latLonAltBox(); +} - this->addDecoration(outline); - } +void GeoLineStringGraphicsItem::paint(GeoPainter* painter, const ViewportParams* viewport , const QString &layer) +{ + if (layer.endsWith("/outline")) { + paintOutline(painter, viewport); + } else if (layer.endsWith("/label")) { + paintLabel(painter, viewport); + } else if (layer.endsWith("/inline")) { + paintInline(painter, viewport); + } else { + painter->drawPolyline(*m_lineString); } } -void GeoLineStringGraphicsItem::setLineString( const GeoDataLineString* lineString ) +void GeoLineStringGraphicsItem::paintInline(GeoPainter* painter, const ViewportParams* viewport) { - m_lineString = lineString; + if ( ( !viewport->resolves( m_lineString->latLonAltBox(), 2) ) ) { + return; + } + + painter->save(); + LabelPositionFlags labelPositionFlags = NoLabel; + QPen currentPen = configurePainter(painter, viewport, labelPositionFlags); + + if ( ! ( currentPen.widthF() < 2.5f ) ) { + if( style()->lineStyle().cosmeticOutline() && + style()->lineStyle().penStyle() == Qt::SolidLine ) { + if ( currentPen.widthF() > 2.5f ) { + currentPen.setWidthF( currentPen.widthF() - 2.0f ); + } + currentPen.setColor( style()->polyStyle().paintedColor() ); + painter->setPen( currentPen ); + painter->drawPolyline(*m_lineString); + } else { + painter->drawPolyline(*m_lineString); + } + } + + painter->restore(); } -const GeoDataLatLonAltBox& GeoLineStringGraphicsItem::latLonAltBox() const +void GeoLineStringGraphicsItem::paintOutline(GeoPainter *painter, const ViewportParams *viewport) { - return m_lineString->latLonAltBox(); + if ( ( !viewport->resolves( m_lineString->latLonAltBox(), 2) ) ) { + return; + } + + painter->save(); + LabelPositionFlags labelPositionFlags = NoLabel; + QPen currentPen = configurePainter(painter, viewport, labelPositionFlags); + if (!( currentPen.widthF() < 2.5f )) { + painter->drawPolyline(*m_lineString); + } + painter->restore(); } -void GeoLineStringGraphicsItem::paint( GeoPainter* painter, const ViewportParams* viewport ) +void GeoLineStringGraphicsItem::paintLabel(GeoPainter *painter, const ViewportParams *viewport) { if ( ( !viewport->resolves( m_lineString->latLonAltBox(), 2) ) ) { return; } + painter->save(); LabelPositionFlags labelPositionFlags = NoLabel; + QPen currentPen = configurePainter(painter, viewport, labelPositionFlags); + + if (!( currentPen.widthF() < 2.5f )) { + QPen pen(QColor(Qt::transparent)); + pen.setWidthF(currentPen.widthF()); + painter->setPen(pen); + QColor const color = style()->polyStyle().paintedColor(); + painter->setBackground(QBrush(color)); + painter->setBackgroundMode(Qt::OpaqueMode); + painter->drawPolyline( *m_lineString, feature()->name(), FollowLine, + style()->labelStyle().paintedColor(), + style()->labelStyle().font()); + } - painter->save(); + painter->restore(); +} +QPen GeoLineStringGraphicsItem::configurePainter(GeoPainter *painter, const ViewportParams *viewport, LabelPositionFlags &labelPositionFlags) const +{ QPen currentPen = painter->pen(); if ( !style() ) { painter->setPen( QPen() ); @@ -122,30 +187,7 @@ } } - if ( ! ( isDecoration() && currentPen.widthF() < 2.5f ) ) - { - if( style()->lineStyle().cosmeticOutline() && - style()->lineStyle().penStyle() == Qt::SolidLine ) { - if ( isDecoration() ) { - painter->drawPolyline( *m_lineString, "", NoLabel ); - } else { - if ( currentPen.widthF() > 2.5f ) { - currentPen.setWidthF( currentPen.widthF() - 2.0f ); - } - currentPen.setColor( style()->polyStyle().paintedColor() ); - painter->setPen( currentPen ); - painter->drawPolyline( *m_lineString, feature()->name(), FollowLine, - style()->labelStyle().paintedColor(), - style()->labelStyle().font()); - } - } else { - painter->drawPolyline( *m_lineString, feature()->name(), labelPositionFlags, - style()->labelStyle().paintedColor(), - style()->labelStyle().font() ); - } - } - - painter->restore(); + return currentPen; } } diff --git a/src/lib/marble/geodata/graphicsitem/GeoPhotoGraphicsItem.h b/src/lib/marble/geodata/graphicsitem/GeoPhotoGraphicsItem.h --- a/src/lib/marble/geodata/graphicsitem/GeoPhotoGraphicsItem.h +++ b/src/lib/marble/geodata/graphicsitem/GeoPhotoGraphicsItem.h @@ -29,7 +29,7 @@ GeoDataPoint point() const; - virtual void paint( GeoPainter* painter, const ViewportParams *viewport ); + virtual void paint(GeoPainter* painter, const ViewportParams *viewport, const QString &layer); virtual const GeoDataLatLonAltBox& latLonAltBox() const; diff --git a/src/lib/marble/geodata/graphicsitem/GeoPhotoGraphicsItem.cpp b/src/lib/marble/geodata/graphicsitem/GeoPhotoGraphicsItem.cpp --- a/src/lib/marble/geodata/graphicsitem/GeoPhotoGraphicsItem.cpp +++ b/src/lib/marble/geodata/graphicsitem/GeoPhotoGraphicsItem.cpp @@ -12,6 +12,7 @@ #include "GeoPainter.h" #include "GeoDataStyle.h" +#include "GeoDataFeature.h" #include "ViewportParams.h" #include @@ -24,10 +25,15 @@ GeoPhotoGraphicsItem::GeoPhotoGraphicsItem( const GeoDataFeature *feature ) : GeoGraphicsItem( feature ) { + if (feature) { + QString const paintLayer = QString("Photo/%1").arg(GeoDataFeature::visualCategoryName(feature->visualCategory())); + setPaintLayers(QStringList() << paintLayer); + } } -void GeoPhotoGraphicsItem::paint( GeoPainter* painter, const ViewportParams* viewport ) +void GeoPhotoGraphicsItem::paint(GeoPainter* painter, const ViewportParams* viewport , const QString &layer) { + Q_UNUSED(layer); /* The code below loads the image lazily (only * when it will actually be displayed). Once it was * loaded but moves out of the viewport, it is unloaded diff --git a/src/lib/marble/geodata/graphicsitem/GeoPointGraphicsItem.h b/src/lib/marble/geodata/graphicsitem/GeoPointGraphicsItem.h --- a/src/lib/marble/geodata/graphicsitem/GeoPointGraphicsItem.h +++ b/src/lib/marble/geodata/graphicsitem/GeoPointGraphicsItem.h @@ -27,7 +27,7 @@ void setPoint( const GeoDataPoint& point ); GeoDataPoint point() const; - virtual void paint( GeoPainter* painter, const ViewportParams *viewport ); + virtual void paint(GeoPainter* painter, const ViewportParams *viewport, const QString &layer); virtual const GeoDataLatLonAltBox& latLonAltBox() const; diff --git a/src/lib/marble/geodata/graphicsitem/GeoPointGraphicsItem.cpp b/src/lib/marble/geodata/graphicsitem/GeoPointGraphicsItem.cpp --- a/src/lib/marble/geodata/graphicsitem/GeoPointGraphicsItem.cpp +++ b/src/lib/marble/geodata/graphicsitem/GeoPointGraphicsItem.cpp @@ -11,13 +11,18 @@ #include "GeoPointGraphicsItem.h" #include "GeoPainter.h" +#include "GeoDataFeature.h" namespace Marble { GeoPointGraphicsItem::GeoPointGraphicsItem( const GeoDataFeature *feature ) : GeoGraphicsItem( feature ) { + if (feature) { + QString const paintLayer = QString("Point/%1").arg(GeoDataFeature::visualCategoryName(feature->visualCategory())); + setPaintLayers(QStringList() << paintLayer); + } } void GeoPointGraphicsItem::setPoint( const GeoDataPoint& point ) @@ -30,9 +35,10 @@ return m_point; } -void GeoPointGraphicsItem::paint( GeoPainter* painter, const ViewportParams* viewport ) +void GeoPointGraphicsItem::paint(GeoPainter* painter, const ViewportParams* viewport , const QString &layer) { - Q_UNUSED( viewport ); + Q_UNUSED(viewport); + Q_UNUSED(layer); painter->drawPoint( m_point ); } diff --git a/src/lib/marble/geodata/graphicsitem/GeoPolygonGraphicsItem.h b/src/lib/marble/geodata/graphicsitem/GeoPolygonGraphicsItem.h --- a/src/lib/marble/geodata/graphicsitem/GeoPolygonGraphicsItem.h +++ b/src/lib/marble/geodata/graphicsitem/GeoPolygonGraphicsItem.h @@ -32,19 +32,24 @@ virtual const GeoDataLatLonAltBox& latLonAltBox() const; - virtual void paint( GeoPainter* painter, const ViewportParams *viewport ); - -protected: - virtual void createDecorations(); + void paint(GeoPainter* painter, const ViewportParams *viewport, const QString &layer); private: + void paintFrame( GeoPainter* painter, const ViewportParams *viewport ); + void paintRoof( GeoPainter* painter, const ViewportParams *viewport ); + QPointF buildingOffset(const QPointF &point, const ViewportParams *viewport, bool* isCameraAboveBuilding=0) const; double extractBuildingHeight(double defaultValue) const; - void screenPolygons(const ViewportParams *viewport, const GeoDataPolygon* polygon, QVector &polygons, QVector &outlines); + void screenPolygons(const ViewportParams *viewport, const GeoDataPolygon* polygon, QVector &polygons, QVector &outlines) const; + QPen configurePainter(GeoPainter* painter, const ViewportParams *viewport, bool isBuildingFrame); + void determineBuildingHeight(); + void initializeBuildingPainting(const GeoPainter* painter, const ViewportParams *viewport, + bool &drawAccurate3D, bool &isCameraAboveBuilding, bool &hasInnerBoundaries, + QVector& outlinePolygons, + QVector& innerPolygons) const; const GeoDataPolygon *const m_polygon; const GeoDataLinearRing *const m_ring; - static const float s_decorationZValue; double m_buildingHeight; QString m_cachedTexturePath; QColor m_cachedTextureColor; diff --git a/src/lib/marble/geodata/graphicsitem/GeoPolygonGraphicsItem.cpp b/src/lib/marble/geodata/graphicsitem/GeoPolygonGraphicsItem.cpp --- a/src/lib/marble/geodata/graphicsitem/GeoPolygonGraphicsItem.cpp +++ b/src/lib/marble/geodata/graphicsitem/GeoPolygonGraphicsItem.cpp @@ -18,6 +18,7 @@ #include "ViewportParams.h" #include "GeoDataStyle.h" #include "MarbleDirs.h" +#include "MarbleDebug.h" #include "OsmPlacemarkData.h" #include @@ -32,27 +33,26 @@ m_ring( 0 ), m_buildingHeight(0.0) { + determineBuildingHeight(); } GeoPolygonGraphicsItem::GeoPolygonGraphicsItem( const GeoDataFeature *feature, const GeoDataLinearRing* ring ) : GeoGraphicsItem( feature ), m_polygon( 0 ), m_ring( ring ), m_buildingHeight(0.0) { + determineBuildingHeight(); } -const float GeoPolygonGraphicsItem::s_decorationZValue = -0.001; - -void GeoPolygonGraphicsItem::createDecorations() +void GeoPolygonGraphicsItem::determineBuildingHeight() { - if (isDecoration() || (!m_polygon && !m_ring )) { + if (!m_polygon && !m_ring ) { return; } - GeoPolygonGraphicsItem *fake3D; - - switch ( feature()->visualCategory() ) { + GeoDataFeature::GeoDataVisualCategory const visualCategory = feature()->visualCategory(); + switch (visualCategory) { case GeoDataFeature::Building: //case GeoDataFeature::AccomodationCamping: case GeoDataFeature::AccomodationHostel: @@ -97,22 +97,49 @@ case GeoDataFeature::ReligionShinto: case GeoDataFeature::ReligionSikh: { - fake3D = m_polygon ? new GeoPolygonGraphicsItem( feature(), m_polygon ) : new GeoPolygonGraphicsItem( feature(), m_ring ); double const height = extractBuildingHeight(8.0); m_buildingHeight = qBound(1.0, height, 1000.0); - fake3D->m_buildingHeight = m_buildingHeight; setZValue(this->zValue() + m_buildingHeight); - fake3D->setZValue(this->zValue() + s_decorationZValue); Q_ASSERT(m_buildingHeight > 0.0); + + QStringList paintLayers; + paintLayers << QString("Polygon/Building/frame"); + paintLayers << QString("Polygon/Building/roof"); + setPaintLayers(paintLayers); } break; default: - fake3D = nullptr; + QString const paintLayer = QString("Polygon/%1").arg(GeoDataFeature::visualCategoryName(visualCategory)); + setPaintLayers(QStringList() << paintLayer); break; } +} - this->addDecoration(fake3D); +void GeoPolygonGraphicsItem::initializeBuildingPainting(const GeoPainter* painter, const ViewportParams *viewport, + bool &drawAccurate3D, bool &isCameraAboveBuilding, bool &hasInnerBoundaries, + QVector& outlinePolygons, + QVector& innerPolygons) const +{ + drawAccurate3D = false; + isCameraAboveBuilding = false; + + QPointF offsetAtCorner = buildingOffset(QPointF(0, 0), viewport, &isCameraAboveBuilding); + qreal maxOffset = qMax( qAbs( offsetAtCorner.x() ), qAbs( offsetAtCorner.y() ) ); + drawAccurate3D = painter->mapQuality() == HighQuality ? maxOffset > 5.0 : maxOffset > 8.0; + + // Since subtracting one fully contained polygon from another results in a single + // polygon with a "connecting line" between the inner and outer part we need + // to first paint the inner area with no pen and then the outlines with the correct pen. + hasInnerBoundaries = m_polygon ? !m_polygon->innerBoundaries().isEmpty() : false; + if (m_polygon) { + if (hasInnerBoundaries) { + screenPolygons(viewport, m_polygon, innerPolygons, outlinePolygons); + } + viewport->screenCoordinates(m_polygon->outerBoundary(), outlinePolygons); + } else if (m_ring) { + viewport->screenCoordinates(*m_ring, outlinePolygons); + } } QPointF GeoPolygonGraphicsItem::buildingOffset(const QPointF &point, const ViewportParams *viewport, bool* isCameraAboveBuilding) const @@ -179,13 +206,219 @@ } } -void GeoPolygonGraphicsItem::paint( GeoPainter* painter, const ViewportParams* viewport ) +void GeoPolygonGraphicsItem::paint( GeoPainter* painter, const ViewportParams* viewport, const QString &layer ) { + if (layer.endsWith("/frame")) { + paintFrame(painter, viewport); + } else if (layer.endsWith("/roof")) { + paintRoof(painter, viewport); + } else if (m_buildingHeight == 0.0) { + painter->save(); + configurePainter(painter, viewport, false); + if ( m_polygon ) { + painter->drawPolygon( *m_polygon ); + } else if ( m_ring ) { + painter->drawPolygon( *m_ring ); + } + + bool const hasIcon = !style()->iconStyle().iconPath().isEmpty(); + if (hasIcon) { + QImage const icon = style()->iconStyle().scaledIcon(); + painter->drawImage(latLonAltBox().center(), icon); + } + painter->restore(); + } else { + mDebug() << "Didn't expect to have to paint layer " << layer << ", ignoring it."; + } +} + +void GeoPolygonGraphicsItem::paintRoof( GeoPainter* painter, const ViewportParams* viewport ) +{ + bool drawAccurate3D; + bool isCameraAboveBuilding; + bool hasInnerBoundaries; + QVector outlinePolygons; + QVector innerPolygons; + initializeBuildingPainting(painter, viewport, drawAccurate3D, isCameraAboveBuilding, hasInnerBoundaries, outlinePolygons, innerPolygons); + if (!isCameraAboveBuilding) { + return; // do not render roof if we look inside the building + } + + painter->save(); + QPen const currentPen = configurePainter(painter, viewport, false); + + bool const hasIcon = !style()->iconStyle().iconPath().isEmpty(); + qreal maxSize(0.0); + QPointF roofCenter; + + if (hasInnerBoundaries) { + painter->setPen(Qt::NoPen); + } + + // first paint the area and icon (and the outline if there are no inner boundaries) + + foreach(QPolygonF* outlinePolygon, outlinePolygons) { + QRectF const boundingRect = outlinePolygon->boundingRect(); + if (hasIcon) { + QSizeF const polygonSize = boundingRect.size(); + qreal size = polygonSize.width() * polygonSize.height(); + if (size > maxSize) { + maxSize = size; + roofCenter = boundingRect.center() + buildingOffset(boundingRect.center(), viewport); + } + } + if ( drawAccurate3D) { + QPolygonF buildingRoof; + foreach(const QPointF &point, *outlinePolygon) { + buildingRoof << point + buildingOffset(point, viewport); + } + if (hasInnerBoundaries) { + QRegion clip(buildingRoof.toPolygon()); + + foreach(QPolygonF* innerPolygon, innerPolygons) { + QPolygonF buildingInner; + foreach(const QPointF &point, *innerPolygon) { + buildingInner << point + buildingOffset(point, viewport); + } + clip-=QRegion(buildingInner.toPolygon()); + } + painter->setClipRegion(clip); + } + painter->drawPolygon(buildingRoof); + } else { + QPointF const offset = buildingOffset(boundingRect.center(), viewport); + painter->translate(offset); + if (hasInnerBoundaries) { + QRegion clip(outlinePolygon->toPolygon()); + + foreach(QPolygonF* clipPolygon, innerPolygons) { + clip-=QRegion(clipPolygon->toPolygon()); + } + painter->setClipRegion(clip); + } + painter->drawPolygon(*outlinePolygon); + painter->translate(-offset); + } + if (hasIcon && !roofCenter.isNull()) { + QImage const icon = style()->iconStyle().scaledIcon(); + QPointF const iconCenter(icon.size().width()/2.0, icon.size().height()/2.0); + painter->drawImage(roofCenter-iconCenter, icon); + } + } + + // then paint the outlines if there are inner boundaries + + if (hasInnerBoundaries) { + painter->setPen(currentPen); + foreach(QPolygonF * polygon, outlinePolygons) { + QRectF const boundingRect = polygon->boundingRect(); + if ( drawAccurate3D) { + QPolygonF buildingRoof; + foreach(const QPointF &point, *polygon) { + buildingRoof << point + buildingOffset(point, viewport); + } + painter->drawPolyline(buildingRoof); + } else { + QPointF const offset = buildingOffset(boundingRect.center(), viewport); + painter->translate(offset); + painter->drawPolyline(*polygon); + painter->translate(-offset); + } + } + } + + qDeleteAll(outlinePolygons); + painter->restore(); +} + + +void GeoPolygonGraphicsItem::paintFrame(GeoPainter *painter, const ViewportParams *viewport) { + if (m_buildingHeight == 0.0) { + return; + } + + if ((m_polygon && !viewport->resolves(m_polygon->outerBoundary().latLonAltBox(), 4)) + || (m_ring && !viewport->resolves(m_ring->latLonAltBox(), 4))) { + return; + } + painter->save(); - bool const isBuildingFrame = isDecoration(); - bool const isBuildingRoof = !isDecoration() && !decorations().isEmpty(); + bool drawAccurate3D; + bool isCameraAboveBuilding; + bool hasInnerBoundaries; + QVector outlinePolygons; + QVector innerPolygons; + initializeBuildingPainting(painter, viewport, drawAccurate3D, isCameraAboveBuilding, hasInnerBoundaries, outlinePolygons, innerPolygons); + + configurePainter(painter, viewport, true); + foreach(QPolygonF* outlinePolygon, outlinePolygons) { + if (outlinePolygon->isEmpty()) { + continue; + } + if ( drawAccurate3D && isCameraAboveBuilding ) { + // draw the building sides + int const size = outlinePolygon->size(); + QPointF & a = (*outlinePolygon)[0]; + QPointF shiftA = a + buildingOffset(a, viewport); + for (int i=1; isetPen(QPen(painter->brush().color(), 1.5)); + } + painter->drawPolygon(buildingSide); + a = b; + shiftA = shiftB; + } + } else { + // don't draw the building sides - just draw the base frame instead + if (hasInnerBoundaries) { + QRegion clip(outlinePolygon->toPolygon()); + + foreach(QPolygonF* clipPolygon, innerPolygons) { + clip-=QRegion(clipPolygon->toPolygon()); + } + painter->setClipRegion(clip); + } + painter->drawPolygon(*outlinePolygon); + } + } + qDeleteAll(outlinePolygons); + + painter->restore(); +} + +void GeoPolygonGraphicsItem::screenPolygons(const ViewportParams *viewport, const GeoDataPolygon * polygon, QVector & innerPolygons, QVector & outlines) const { + + Q_ASSERT(polygon); + + QVector outerPolygons; + viewport->screenCoordinates( polygon->outerBoundary(), outerPolygons ); + + outlines << outerPolygons; + + bool const hasInnerBoundaries = !m_polygon->innerBoundaries().isEmpty(); + + QVector innerBoundaries = polygon->innerBoundaries(); + foreach( const GeoDataLinearRing& itInnerBoundary, innerBoundaries ) { + QVector innerPolygonsPerBoundary; + viewport->screenCoordinates( itInnerBoundary, innerPolygonsPerBoundary ); + + if ( hasInnerBoundaries ) { + outlines << innerPolygonsPerBoundary; + foreach( QPolygonF* innerPolygonPerBoundary, innerPolygonsPerBoundary ) { + innerPolygons << innerPolygonPerBoundary; + } + } + + } +} +QPen GeoPolygonGraphicsItem::configurePainter(GeoPainter *painter, const ViewportParams *viewport, bool isBuildingFrame) +{ QPen currentPen = painter->pen(); if ( !style() ) { @@ -248,201 +481,7 @@ } } - if ( isBuildingFrame || isBuildingRoof ) { - - if ((m_polygon && !viewport->resolves(m_polygon->outerBoundary().latLonAltBox(), 4)) - || (m_ring && !viewport->resolves(m_ring->latLonAltBox(), 4))) { - painter->restore(); - return; - } - - bool drawAccurate3D = false; - bool isCameraAboveBuilding = false; - - QPointF offsetAtCorner = buildingOffset(QPointF(0, 0), viewport, &isCameraAboveBuilding); - qreal maxOffset = qMax( qAbs( offsetAtCorner.x() ), qAbs( offsetAtCorner.y() ) ); - drawAccurate3D = painter->mapQuality() == HighQuality ? maxOffset > 5.0 : maxOffset > 8.0; - - // Since subtracting one fully contained polygon from another results in a single - // polygon with a "connecting line" between the inner and outer part we need - // to first paint the inner area with no pen and then the outlines with the correct pen. - QVector outlinePolygons; - QVector innerPolygons; - bool const hasInnerBoundaries = m_polygon ? !m_polygon->innerBoundaries().isEmpty() : false; - if (m_polygon) { - if (hasInnerBoundaries) { - screenPolygons(viewport, m_polygon, innerPolygons, outlinePolygons); - } - viewport->screenCoordinates(m_polygon->outerBoundary(), outlinePolygons); - } else if (m_ring) { - viewport->screenCoordinates(*m_ring, outlinePolygons); - } - - if ( isBuildingFrame ) { - foreach(QPolygonF* outlinePolygon, outlinePolygons) { - if (outlinePolygon->isEmpty()) { - continue; - } - if ( drawAccurate3D && isCameraAboveBuilding ) { - // draw the building sides - int const size = outlinePolygon->size(); - QPointF & a = (*outlinePolygon)[0]; - QPointF shiftA = a + buildingOffset(a, viewport); - for (int i=1; isetPen(QPen(painter->brush().color(), 1.5)); - } - painter->drawPolygon(buildingSide); - a = b; - shiftA = shiftB; - } - } else { - // don't draw the building sides - just draw the base frame instead - if (hasInnerBoundaries) { - QRegion clip(outlinePolygon->toPolygon()); - - foreach(QPolygonF* clipPolygon, innerPolygons) { - clip-=QRegion(clipPolygon->toPolygon()); - } - painter->setClipRegion(clip); - } - painter->drawPolygon(*outlinePolygon); - } - } - } else if (isBuildingRoof) { - if (!isCameraAboveBuilding) { - painter->restore(); - return; // do not render roof if we look inside the building - } - - bool const hasIcon = !style()->iconStyle().iconPath().isEmpty(); - qreal maxSize(0.0); - QPointF roofCenter; - - if (hasInnerBoundaries) { - painter->setPen(Qt::NoPen); - } - - // first paint the area and icon (and the outline if there are no inner boundaries) - - foreach(QPolygonF* outlinePolygon, outlinePolygons) { - QRectF const boundingRect = outlinePolygon->boundingRect(); - if (hasIcon) { - QSizeF const polygonSize = boundingRect.size(); - qreal size = polygonSize.width() * polygonSize.height(); - if (size > maxSize) { - maxSize = size; - roofCenter = boundingRect.center() + buildingOffset(boundingRect.center(), viewport); - } - } - if ( drawAccurate3D) { - QPolygonF buildingRoof; - foreach(const QPointF &point, *outlinePolygon) { - buildingRoof << point + buildingOffset(point, viewport); - } - if (hasInnerBoundaries) { - QRegion clip(buildingRoof.toPolygon()); - - foreach(QPolygonF* innerPolygon, innerPolygons) { - QPolygonF buildingInner; - foreach(const QPointF &point, *innerPolygon) { - buildingInner << point + buildingOffset(point, viewport); - } - clip-=QRegion(buildingInner.toPolygon()); - } - painter->setClipRegion(clip); - } - painter->drawPolygon(buildingRoof); - } else { - QPointF const offset = buildingOffset(boundingRect.center(), viewport); - painter->translate(offset); - if (hasInnerBoundaries) { - QRegion clip(outlinePolygon->toPolygon()); - - foreach(QPolygonF* clipPolygon, innerPolygons) { - clip-=QRegion(clipPolygon->toPolygon()); - } - painter->setClipRegion(clip); - } - painter->drawPolygon(*outlinePolygon); - painter->translate(-offset); - } - if (hasIcon && !roofCenter.isNull()) { - QImage const icon = style()->iconStyle().scaledIcon(); - QPointF const iconCenter(icon.size().width()/2.0, icon.size().height()/2.0); - painter->drawImage(roofCenter-iconCenter, icon); - } - } - - // then paint the outlines if there are inner boundaries - - if (hasInnerBoundaries) { - painter->setPen(currentPen); - foreach(QPolygonF * polygon, outlinePolygons) { - QRectF const boundingRect = polygon->boundingRect(); - if ( drawAccurate3D) { - QPolygonF buildingRoof; - foreach(const QPointF &point, *polygon) { - buildingRoof << point + buildingOffset(point, viewport); - } - painter->drawPolyline(buildingRoof); - } else { - QPointF const offset = buildingOffset(boundingRect.center(), viewport); - painter->translate(offset); - painter->drawPolyline(*polygon); - painter->translate(-offset); - } - } - } - } - qDeleteAll(outlinePolygons); - - } else { - if ( m_polygon ) { - painter->drawPolygon( *m_polygon ); - } else if ( m_ring ) { - painter->drawPolygon( *m_ring ); - } - - bool const hasIcon = !style()->iconStyle().iconPath().isEmpty(); - if (hasIcon) { - QImage const icon = style()->iconStyle().scaledIcon(); - painter->drawImage(latLonAltBox().center(), icon); - } - } - - painter->restore(); -} - -void GeoPolygonGraphicsItem::screenPolygons(const ViewportParams *viewport, const GeoDataPolygon * polygon, QVector & innerPolygons, QVector & outlines) { - - Q_ASSERT(polygon); - - QVector outerPolygons; - viewport->screenCoordinates( polygon->outerBoundary(), outerPolygons ); - - outlines << outerPolygons; - - bool const hasInnerBoundaries = !m_polygon->innerBoundaries().isEmpty(); - - QVector innerBoundaries = polygon->innerBoundaries(); - foreach( const GeoDataLinearRing& itInnerBoundary, innerBoundaries ) { - QVector innerPolygonsPerBoundary; - viewport->screenCoordinates( itInnerBoundary, innerPolygonsPerBoundary ); - - if ( hasInnerBoundaries ) { - outlines << innerPolygonsPerBoundary; - foreach( QPolygonF* innerPolygonPerBoundary, innerPolygonsPerBoundary ) { - innerPolygons << innerPolygonPerBoundary; - } - } - - } + return currentPen; } - } diff --git a/src/lib/marble/geodata/graphicsitem/GeoTrackGraphicsItem.h b/src/lib/marble/geodata/graphicsitem/GeoTrackGraphicsItem.h --- a/src/lib/marble/geodata/graphicsitem/GeoTrackGraphicsItem.h +++ b/src/lib/marble/geodata/graphicsitem/GeoTrackGraphicsItem.h @@ -26,7 +26,7 @@ void setTrack( const GeoDataTrack *track ); - virtual void paint( GeoPainter *painter, const ViewportParams *viewport ); + virtual void paint(GeoPainter *painter, const ViewportParams *viewport, const QString &layer); private: const GeoDataTrack *m_track; diff --git a/src/lib/marble/geodata/graphicsitem/GeoTrackGraphicsItem.cpp b/src/lib/marble/geodata/graphicsitem/GeoTrackGraphicsItem.cpp --- a/src/lib/marble/geodata/graphicsitem/GeoTrackGraphicsItem.cpp +++ b/src/lib/marble/geodata/graphicsitem/GeoTrackGraphicsItem.cpp @@ -12,27 +12,32 @@ #include "GeoDataLineString.h" #include "GeoDataTrack.h" +#include "GeoDataFeature.h" #include "MarbleDebug.h" using namespace Marble; GeoTrackGraphicsItem::GeoTrackGraphicsItem( const GeoDataFeature *feature, const GeoDataTrack *track ) : GeoLineStringGraphicsItem( feature, track->lineString() ) { setTrack( track ); + if (feature) { + QString const paintLayer = QString("Track/%1").arg(GeoDataFeature::visualCategoryName(feature->visualCategory())); + setPaintLayers(QStringList() << paintLayer); + } } void GeoTrackGraphicsItem::setTrack( const GeoDataTrack* track ) { m_track = track; update(); } -void GeoTrackGraphicsItem::paint( GeoPainter *painter, const ViewportParams *viewport ) +void GeoTrackGraphicsItem::paint(GeoPainter *painter, const ViewportParams *viewport , const QString &layer) { + Q_UNUSED(layer); update(); - - GeoLineStringGraphicsItem::paint( painter, viewport ); + GeoLineStringGraphicsItem::paint(painter, viewport, layer); } void GeoTrackGraphicsItem::update() diff --git a/src/lib/marble/graphicsview/GeoGraphicsItem.h b/src/lib/marble/graphicsview/GeoGraphicsItem.h --- a/src/lib/marble/graphicsview/GeoGraphicsItem.h +++ b/src/lib/marble/graphicsview/GeoGraphicsItem.h @@ -126,31 +126,18 @@ * Note that depending on the projection and zoom level, the item may be visible more than once, * which is taken care of by GeoPainter. */ - virtual void paint( GeoPainter *painter, const ViewportParams *viewport ) = 0; + virtual void paint(GeoPainter *painter, const ViewportParams *viewport, const QString &layer) = 0; void setHighlighted( bool highlight ); bool isHighlighted() const; - const QList& decorations(); + QStringList paintLayers() const; - bool isDecoration() const; + void setPaintLayers(const QStringList &paintLayers); protected: GeoGraphicsItemPrivate *const d; - - /** - * Creates a new decoration for this item. - * - * Override this function to create a new type of decoration, - * e.g. outlines for lines or "fake 3D effect" for polygons. - * After a decoration was created add it to the item with - * addDecoration(). You can create multiple decoration for a - * single GeoGraphicsItem. - */ - virtual void createDecorations(); - - void addDecoration(GeoGraphicsItem* decoration); }; } // Namespace Marble diff --git a/src/lib/marble/graphicsview/GeoGraphicsItem.cpp b/src/lib/marble/graphicsview/GeoGraphicsItem.cpp --- a/src/lib/marble/graphicsview/GeoGraphicsItem.cpp +++ b/src/lib/marble/graphicsview/GeoGraphicsItem.cpp @@ -29,7 +29,6 @@ GeoGraphicsItem::~GeoGraphicsItem() { - qDeleteAll< QList >(d->m_decorations); delete d; } @@ -41,9 +40,6 @@ void GeoGraphicsItem::setVisible( bool visible ) { setFlag( ItemIsVisible, visible ); - foreach( GeoGraphicsItem* decoration, d->m_decorations ) { - decoration->setVisible( visible ); - } } GeoGraphicsItem::GeoGraphicsItemFlags GeoGraphicsItem::flags() const @@ -78,17 +74,11 @@ void GeoGraphicsItem::setLatLonAltBox( const GeoDataLatLonAltBox& latLonAltBox ) { d->m_latLonAltBox = latLonAltBox; - foreach( GeoGraphicsItem* decoration, d->m_decorations ) { - decoration->setLatLonAltBox( latLonAltBox ); - } } void GeoGraphicsItem::setStyle( const GeoDataStyle::ConstPtr &style ) { d->m_style = style; - foreach( GeoGraphicsItem* decoration, d->m_decorations ) { - decoration->setStyle( style ); - } } void GeoGraphicsItem::setHighlightStyle( const GeoDataStyle::ConstPtr &highlightStyle) @@ -98,9 +88,6 @@ * and assign the new style @highlightStyle */ d->m_highlightStyle = highlightStyle; - foreach( GeoGraphicsItem* decoration, d->m_decorations ) { - decoration->setHighlightStyle( highlightStyle ); - } } GeoDataStyle::ConstPtr GeoGraphicsItem::style() const @@ -128,65 +115,35 @@ void GeoGraphicsItem::setHighlighted( bool highlight ) { d->m_highlighted = highlight; - foreach( GeoGraphicsItem* decoration, d->m_decorations ) { - decoration->setHighlighted( highlight ); - } } bool GeoGraphicsItem::isHighlighted() const { return d->m_highlighted; } -int GeoGraphicsItem::minZoomLevel() const -{ - return d->m_minZoomLevel; -} - -void GeoGraphicsItem::setMinZoomLevel(int zoomLevel) +QStringList GeoGraphicsItem::paintLayers() const { - d->m_minZoomLevel = zoomLevel; - foreach( GeoGraphicsItem* decoration, d->m_decorations ) { - decoration->setMinZoomLevel( zoomLevel ); - } + return d->m_paintLayers; } -const QList& GeoGraphicsItem::decorations() +void GeoGraphicsItem::setPaintLayers(const QStringList &paintLayers) { - if ( d->m_decorations.isEmpty() ) { - createDecorations(); - } - - return d->m_decorations; + d->m_paintLayers = paintLayers; } -void GeoGraphicsItem::addDecoration(GeoGraphicsItem* decoration) +int GeoGraphicsItem::minZoomLevel() const { - if (decoration != nullptr) { - decoration->d->m_isDecoration = true; - - decoration->setLatLonAltBox(this->latLonAltBox()); - decoration->setFlags(this->flags()); - decoration->setHighlighted(this->isHighlighted()); - decoration->setStyle(this->style()); - decoration->setMinZoomLevel(this->minZoomLevel()); - decoration->setVisible(this->visible()); - - d->m_decorations.append(decoration); - } + return d->m_minZoomLevel; } -bool GeoGraphicsItem::isDecoration() const +void GeoGraphicsItem::setMinZoomLevel(int zoomLevel) { - return d->m_isDecoration; + d->m_minZoomLevel = zoomLevel; } bool GeoGraphicsItem::zValueLessThan(GeoGraphicsItem *one, GeoGraphicsItem *two) { return one->d->m_zValue < two->d->m_zValue; } -void GeoGraphicsItem::createDecorations() -{ - return; -} diff --git a/src/lib/marble/graphicsview/GeoGraphicsItem_p.h b/src/lib/marble/graphicsview/GeoGraphicsItem_p.h --- a/src/lib/marble/graphicsview/GeoGraphicsItem_p.h +++ b/src/lib/marble/graphicsview/GeoGraphicsItem_p.h @@ -28,7 +28,6 @@ m_minZoomLevel( 0 ), m_feature( feature ), m_latLonAltBox(), - m_isDecoration( false ), m_highlighted( false ) { } @@ -45,8 +44,7 @@ GeoDataLatLonAltBox m_latLonAltBox; GeoDataStyle::ConstPtr m_style; - bool m_isDecoration; - QList m_decorations; + QStringList m_paintLayers; // To highlight a placemark bool m_highlighted; diff --git a/src/lib/marble/layers/GeometryLayer.cpp b/src/lib/marble/layers/GeometryLayer.cpp --- a/src/lib/marble/layers/GeometryLayer.cpp +++ b/src/lib/marble/layers/GeometryLayer.cpp @@ -76,21 +76,18 @@ QMap m_osmRelationItems; private: - static void initializeDefaultValues(); + static QString createPaintLayerOrder(const QString &itemType, GeoDataFeature::GeoDataVisualCategory visualCategory, const QString &subType = QString()); - static int s_defaultZValues[GeoDataFeature::LastIndex]; static int s_defaultMinZoomLevels[GeoDataFeature::LastIndex]; static bool s_defaultValuesInitialized; static int s_maximumZoomLevel; - static const int s_defaultZValue; }; -int GeometryLayerPrivate::s_defaultZValues[GeoDataFeature::LastIndex]; int GeometryLayerPrivate::s_defaultMinZoomLevels[GeoDataFeature::LastIndex]; bool GeometryLayerPrivate::s_defaultValuesInitialized = false; int GeometryLayerPrivate::s_maximumZoomLevel = 0; -const int GeometryLayerPrivate::s_defaultZValue = 50; +QStringList s_paintLayerOrder; GeometryLayerPrivate::GeometryLayerPrivate( const QAbstractItemModel *model ) : m_model( model ) @@ -103,6 +100,16 @@ return s_maximumZoomLevel; } +QString GeometryLayerPrivate::createPaintLayerOrder(const QString &itemType, GeoDataFeature::GeoDataVisualCategory visualCategory, const QString &subType) +{ + QString const category = GeoDataFeature::visualCategoryName(visualCategory); + if (subType.isEmpty()) { + return QString("%1/%2").arg(itemType).arg(category); + } else { + return QString("%1/%2/%3").arg(itemType).arg(category).arg(subType); + } +} + GeometryLayer::GeometryLayer( const QAbstractItemModel *model ) : d( new GeometryLayerPrivate( model ) ) { @@ -140,77 +147,91 @@ return; for ( int i = 0; i < GeoDataFeature::LastIndex; i++ ) - s_defaultZValues[i] = s_defaultZValue; - - for ( int i = 0; i < GeoDataFeature::LastIndex; i++ ) s_defaultMinZoomLevels[i] = 15; - s_defaultZValues[GeoDataFeature::None] = 0; - - //Amenity - s_defaultZValues[GeoDataFeature::AmenityGraveyard] = s_defaultZValue - 12; - - s_defaultZValues[GeoDataFeature::EducationCollege] = s_defaultZValue - 12; - s_defaultZValues[GeoDataFeature::EducationSchool] = s_defaultZValue - 12; - s_defaultZValues[GeoDataFeature::EducationUniversity] = s_defaultZValue - 12; - s_defaultZValues[GeoDataFeature::HealthHospital] = s_defaultZValue - 12; - - //Landuse - - for ( int i = GeoDataFeature::LanduseAllotments; i <= GeoDataFeature::LanduseVineyard; i++ ) - s_defaultZValues[(GeoDataFeature::GeoDataVisualCategory)i] = s_defaultZValue - 17; - - s_defaultZValues[GeoDataFeature::NaturalWood] = s_defaultZValue - 15; - s_defaultZValues[GeoDataFeature::NaturalBeach] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::NaturalWetland] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::NaturalGlacier] = s_defaultZValue - 10; - s_defaultZValues[GeoDataFeature::NaturalScrub] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::NaturalWater] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::NaturalCliff] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::NaturalPeak] = s_defaultZValue - 13; - - //Military - - s_defaultZValues[GeoDataFeature::MilitaryDangerArea] = s_defaultZValue - 10; - - //Leisure - - s_defaultZValues[GeoDataFeature::LeisurePark] = s_defaultZValue - 14; - s_defaultZValues[GeoDataFeature::LeisurePlayground] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::LeisurePitch] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::LeisureSportsCentre] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::LeisureStadium] = s_defaultZValue - 13; - s_defaultZValues[GeoDataFeature::LeisureTrack] = s_defaultZValue - 13; - - s_defaultZValues[GeoDataFeature::TransportParking] = s_defaultZValue - 13; - - s_defaultZValues[GeoDataFeature::ManmadeBridge] = s_defaultZValue - 12; - s_defaultZValues[GeoDataFeature::BarrierCityWall] = s_defaultZValue - 1; - - s_defaultZValues[GeoDataFeature::HighwayUnknown] = s_defaultZValue - 11; - s_defaultZValues[GeoDataFeature::HighwayPath] = s_defaultZValue - 10; - s_defaultZValues[GeoDataFeature::HighwayTrack] = s_defaultZValue - 9; - s_defaultZValues[GeoDataFeature::HighwaySteps] = s_defaultZValue - 8; - s_defaultZValues[GeoDataFeature::HighwayFootway] = s_defaultZValue - 8; - s_defaultZValues[GeoDataFeature::HighwayCycleway] = s_defaultZValue - 8; - s_defaultZValues[GeoDataFeature::HighwayService] = s_defaultZValue - 7; - s_defaultZValues[GeoDataFeature::HighwayResidential] = s_defaultZValue - 7; - s_defaultZValues[GeoDataFeature::HighwayLivingStreet] = s_defaultZValue - 7; - s_defaultZValues[GeoDataFeature::HighwayPedestrian] = s_defaultZValue - 6; - s_defaultZValues[GeoDataFeature::HighwayRoad] = s_defaultZValue - 6; - s_defaultZValues[GeoDataFeature::HighwayUnclassified] = s_defaultZValue - 6; - s_defaultZValues[GeoDataFeature::HighwayTertiary] = s_defaultZValue - 5; - s_defaultZValues[GeoDataFeature::HighwaySecondary] = s_defaultZValue - 4; - s_defaultZValues[GeoDataFeature::HighwayPrimary] = s_defaultZValue - 3; - s_defaultZValues[GeoDataFeature::HighwayTrunk] = s_defaultZValue - 2; - s_defaultZValues[GeoDataFeature::HighwayMotorway] = s_defaultZValue - 1; - s_defaultZValues[GeoDataFeature::RailwayRail] = s_defaultZValue - 1; - - s_defaultZValues[GeoDataFeature::HighwayTertiaryLink] = s_defaultZValues[GeoDataFeature::HighwayTertiary]; - s_defaultZValues[GeoDataFeature::HighwaySecondaryLink]= s_defaultZValues[GeoDataFeature::HighwaySecondary]; - s_defaultZValues[GeoDataFeature::HighwayPrimaryLink] = s_defaultZValues[GeoDataFeature::HighwayPrimary]; - s_defaultZValues[GeoDataFeature::HighwayTrunkLink] = s_defaultZValues[GeoDataFeature::HighwayTrunk]; - s_defaultZValues[GeoDataFeature::HighwayMotorwayLink] = s_defaultZValues[GeoDataFeature::HighwayMotorway]; + for ( int i = GeoDataFeature::LanduseAllotments; i <= GeoDataFeature::LanduseVineyard; i++ ) { + if ((GeoDataFeature::GeoDataVisualCategory)i != GeoDataFeature::LanduseGrass) { + s_paintLayerOrder << createPaintLayerOrder("Polygon", (GeoDataFeature::GeoDataVisualCategory)i); + } + } + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::NaturalBeach); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::NaturalWetland); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::NaturalGlacier); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::NaturalCliff); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::NaturalPeak); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::MilitaryDangerArea); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::LeisurePark); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::LeisurePitch); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::LeisureSportsCentre); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::LeisureStadium); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::NaturalWood); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::LanduseGrass); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::LeisurePlayground); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::NaturalScrub); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::LeisureTrack); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::TransportParking); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::TransportParkingSpace); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::ManmadeBridge); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::BarrierCityWall); + + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::AmenityGraveyard); + + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::EducationCollege); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::EducationSchool); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::EducationUniversity); + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::HealthHospital); + + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::NaturalWater); + s_paintLayerOrder << createPaintLayerOrder("LineString", GeoDataFeature::NaturalWater); + for ( int i = GeoDataFeature::HighwaySteps; i <= GeoDataFeature::HighwayMotorway; i++ ) { + s_paintLayerOrder << createPaintLayerOrder("LineString", (GeoDataFeature::GeoDataVisualCategory)i, "outline"); + } + for ( int i = GeoDataFeature::HighwaySteps; i <= GeoDataFeature::HighwayMotorway; i++ ) { + s_paintLayerOrder << createPaintLayerOrder("LineString", (GeoDataFeature::GeoDataVisualCategory)i, "inline"); + } + for ( int i = GeoDataFeature::HighwaySteps; i <= GeoDataFeature::HighwayMotorway; i++ ) { + s_paintLayerOrder << createPaintLayerOrder("LineString", (GeoDataFeature::GeoDataVisualCategory)i, "label"); + } + for ( int i = GeoDataFeature::RailwayRail; i <= GeoDataFeature::RailwayFunicular; i++ ) { + s_paintLayerOrder << createPaintLayerOrder("LineString", (GeoDataFeature::GeoDataVisualCategory)i, "outline"); + } + for ( int i = GeoDataFeature::RailwayRail; i <= GeoDataFeature::RailwayFunicular; i++ ) { + s_paintLayerOrder << createPaintLayerOrder("LineString", (GeoDataFeature::GeoDataVisualCategory)i, "inline"); + } + for ( int i = GeoDataFeature::RailwayRail; i <= GeoDataFeature::RailwayFunicular; i++ ) { + s_paintLayerOrder << createPaintLayerOrder("LineString", (GeoDataFeature::GeoDataVisualCategory)i, "label"); + } + + s_paintLayerOrder << createPaintLayerOrder("Polygon", GeoDataFeature::TransportPlatform); + + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::AmenityGraveyard); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::NaturalWood); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::NaturalBeach); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::NaturalWetland); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::NaturalGlacier); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::NaturalScrub); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::LeisurePark); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::LeisurePlayground); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::LeisurePitch); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::LeisureSportsCentre); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::LeisureStadium); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::LeisureTrack); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::TransportParking); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::ManmadeBridge); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::BarrierCityWall); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::NaturalWater); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::NaturalCliff); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::NaturalPeak); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::EducationCollege); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::EducationSchool); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::EducationUniversity); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::HealthHospital); + s_paintLayerOrder << createPaintLayerOrder("Point", GeoDataFeature::MilitaryDangerArea); + + s_paintLayerOrder << "Polygon/Building/frame"; + s_paintLayerOrder << "Polygon/Building/roof"; + + Q_ASSERT(QSet::fromList(s_paintLayerOrder).size() == s_paintLayerOrder.size()); s_defaultMinZoomLevels[GeoDataFeature::Default] = 1; s_defaultMinZoomLevels[GeoDataFeature::NaturalWater] = 8; @@ -313,40 +334,54 @@ int maxZoomLevel = qMin( qMax( qLn( viewport->radius() *4 / 256 ) / qLn( 2.0 ), 1), GeometryLayerPrivate::maximumZoomLevel() ); QList items = d->m_scene.items( viewport->viewLatLonAltBox(), maxZoomLevel ); - switch ( painter->mapQuality() ) { - case Marble::MapQuality::LowQuality : - case Marble::MapQuality::NormalQuality : - case Marble::MapQuality::HighQuality : - case Marble::MapQuality::PrintQuality : - for ( int i = 0, n = items.size(); i < n; ++i ) { - items << items[i]->decorations(); - } - - break; - default: - break; - } - - // Needs sorting by z-value - qStableSort(items.begin(), items.end(), GeoGraphicsItem::zValueLessThan); - - int painted = 0; + typedef QPair LayerItem; + QList defaultLayer; + int paintedItems = 0; + QHash > paintedFragments; foreach( GeoGraphicsItem* item, items ) { if ( item->latLonAltBox().intersects( viewport->viewLatLonAltBox() ) ) { - item->paint( painter, viewport ); - ++painted; + QStringList paintLayers = item->paintLayers(); + if (paintLayers.isEmpty()) { + mDebug() << item << " provides no paint layers, so I force one onto it."; + paintLayers << QString(); + } + foreach(const auto &layer, paintLayers) { + if (s_paintLayerOrder.contains(layer)) { + paintedFragments[layer] << item; + } else { + defaultLayer << LayerItem(layer, item); + static QSet missingLayers; + if (!missingLayers.contains(layer)) { + mDebug() << "Missing layer " << layer << ", in render order, will render it on top"; + missingLayers << layer; + } + } + } + ++paintedItems; } } + QStringList paintedLayers = s_paintLayerOrder; + foreach(const QString &layer, paintedLayers) { + QList & layerItems = paintedFragments[layer]; + qStableSort(layerItems.begin(), layerItems.end(), GeoGraphicsItem::zValueLessThan); + foreach(auto item, layerItems) { + item->paint(painter, viewport, layer); + } + } + foreach(const auto & item, defaultLayer) { + item.second->paint(painter, viewport, item.first); + } + foreach( ScreenOverlayGraphicsItem* item, d->m_items ) { item->paintEvent( painter, viewport ); } painter->restore(); d->m_runtimeTrace = QString( "Geometries: %1 Drawn: %2 Zoom: %3") .arg( items.size() ) - .arg( painted ) + .arg( paintedItems ) .arg( maxZoomLevel ); return true; } @@ -446,7 +481,6 @@ return; item->setStyle( placemark->style() ); item->setVisible( placemark->isGloballyVisible() ); - item->setZValue( s_defaultZValues[placemark->visualCategory()] ); item->setMinZoomLevel( s_defaultMinZoomLevels[placemark->visualCategory()] ); m_scene.addItem( item ); } diff --git a/src/plugins/render/annotate/AnnotatePlugin.cpp b/src/plugins/render/annotate/AnnotatePlugin.cpp --- a/src/plugins/render/annotate/AnnotatePlugin.cpp +++ b/src/plugins/render/annotate/AnnotatePlugin.cpp @@ -241,7 +241,7 @@ QListIterator iter( m_graphicsItems ); while ( iter.hasNext() ) { - iter.next()->paint( painter, viewport ); + iter.next()->paint( painter, viewport, "Annotation" ); } return true; diff --git a/src/plugins/render/annotate/AreaAnnotation.h b/src/plugins/render/annotate/AreaAnnotation.h --- a/src/plugins/render/annotate/AreaAnnotation.h +++ b/src/plugins/render/annotate/AreaAnnotation.h @@ -43,7 +43,7 @@ * @brief Paints the nodes on the screen and updates the regions which correspond * to each node using the given GeoPainter. */ - virtual void paint( GeoPainter *painter, const ViewportParams *viewport ); + virtual void paint( GeoPainter *painter, const ViewportParams *viewport, const QString &layer ); /** * @brief Returns true if the given QPoint is contained by the current polygon. Note diff --git a/src/plugins/render/annotate/AreaAnnotation.cpp b/src/plugins/render/annotate/AreaAnnotation.cpp --- a/src/plugins/render/annotate/AreaAnnotation.cpp +++ b/src/plugins/render/annotate/AreaAnnotation.cpp @@ -51,16 +51,17 @@ m_interactingObj( InteractingNothing ), m_virtualHovered( -1, -1 ) { - // nothing to do + setPaintLayers(QStringList() << "AreaAnnotation"); } AreaAnnotation::~AreaAnnotation() { delete m_animation; } -void AreaAnnotation::paint( GeoPainter *painter, const ViewportParams *viewport ) +void AreaAnnotation::paint(GeoPainter *painter, const ViewportParams *viewport , const QString &layer) { + Q_UNUSED(layer); m_viewport = viewport; Q_ASSERT( placemark()->geometry()->nodeType() == GeoDataTypes::GeoDataPolygonType ); diff --git a/src/plugins/render/annotate/GroundOverlayFrame.h b/src/plugins/render/annotate/GroundOverlayFrame.h --- a/src/plugins/render/annotate/GroundOverlayFrame.h +++ b/src/plugins/render/annotate/GroundOverlayFrame.h @@ -55,7 +55,7 @@ virtual const char *graphicType() const; protected: - virtual void paint( GeoPainter *painter, const ViewportParams *viewport ); + virtual void paint( GeoPainter *painter, const ViewportParams *viewport, const QString &layer ); virtual bool mousePressEvent( QMouseEvent *event ); virtual bool mouseMoveEvent( QMouseEvent *event ); virtual bool mouseReleaseEvent( QMouseEvent *event ); diff --git a/src/plugins/render/annotate/GroundOverlayFrame.cpp b/src/plugins/render/annotate/GroundOverlayFrame.cpp --- a/src/plugins/render/annotate/GroundOverlayFrame.cpp +++ b/src/plugins/render/annotate/GroundOverlayFrame.cpp @@ -91,10 +91,12 @@ m_rotateIcons.append( QImage( MarbleDirs::systemPath() + "/bitmaps/editarrows/arrow-vertical-active.png" ) ); update(); + setPaintLayers(QStringList() << "GroundOverlayFrame"); } -void GroundOverlayFrame::paint(GeoPainter *painter, const ViewportParams *viewport ) +void GroundOverlayFrame::paint(GeoPainter *painter, const ViewportParams *viewport , const QString &layer) { + Q_UNUSED(layer); m_viewport = viewport; m_regionList.clear(); diff --git a/src/plugins/render/annotate/PlacemarkTextAnnotation.h b/src/plugins/render/annotate/PlacemarkTextAnnotation.h --- a/src/plugins/render/annotate/PlacemarkTextAnnotation.h +++ b/src/plugins/render/annotate/PlacemarkTextAnnotation.h @@ -25,7 +25,7 @@ explicit PlacemarkTextAnnotation( GeoDataPlacemark *placemark ); ~PlacemarkTextAnnotation(); - virtual void paint( GeoPainter *painter, const ViewportParams *viewport ); + virtual void paint(GeoPainter *painter, const ViewportParams *viewport, const QString &layer); virtual bool containsPoint( const QPoint &eventPos ) const; diff --git a/src/plugins/render/annotate/PlacemarkTextAnnotation.cpp b/src/plugins/render/annotate/PlacemarkTextAnnotation.cpp --- a/src/plugins/render/annotate/PlacemarkTextAnnotation.cpp +++ b/src/plugins/render/annotate/PlacemarkTextAnnotation.cpp @@ -42,15 +42,17 @@ newStyle->iconStyle().setIconPath( MarbleDirs::path("bitmaps/redflag_22.png") ); placemark->setStyle( newStyle ); } + setPaintLayers(QStringList() << "PlacemarkTextAnnotation"); } PlacemarkTextAnnotation::~PlacemarkTextAnnotation() { // nothing to do } -void PlacemarkTextAnnotation::paint( GeoPainter *painter, const ViewportParams *viewport ) +void PlacemarkTextAnnotation::paint( GeoPainter *painter, const ViewportParams *viewport, const QString &layer ) { + Q_UNUSED(layer); Q_UNUSED( painter ); m_viewport = viewport; diff --git a/src/plugins/render/annotate/PolylineAnnotation.h b/src/plugins/render/annotate/PolylineAnnotation.h --- a/src/plugins/render/annotate/PolylineAnnotation.h +++ b/src/plugins/render/annotate/PolylineAnnotation.h @@ -35,7 +35,7 @@ * @brief Paints the nodes on the screen and updates the regions which correspond * to each node using the given GeoPainter. */ - virtual void paint( GeoPainter *painter, const ViewportParams *viewport ); + virtual void paint( GeoPainter *painter, const ViewportParams *viewport, const QString &layer ); /** * @brief Returns true if either the polyline's associated region or one of its nodes diff --git a/src/plugins/render/annotate/PolylineAnnotation.cpp b/src/plugins/render/annotate/PolylineAnnotation.cpp --- a/src/plugins/render/annotate/PolylineAnnotation.cpp +++ b/src/plugins/render/annotate/PolylineAnnotation.cpp @@ -53,16 +53,17 @@ m_virtualHoveredNode( -1 ) { - // nothing to do + setPaintLayers(QStringList() << "PolylineAnnotation"); } PolylineAnnotation::~PolylineAnnotation() { delete m_animation; } -void PolylineAnnotation::paint( GeoPainter *painter, const ViewportParams *viewport ) +void PolylineAnnotation::paint(GeoPainter *painter, const ViewportParams *viewport , const QString &layer) { + Q_UNUSED(layer); m_viewport = viewport; Q_ASSERT( placemark()->geometry()->nodeType() == GeoDataTypes::GeoDataLineStringType );