11#include " application/SimulationCanvasWidget.h"
22
33#include < algorithm>
4+ #include < cmath>
45#include < utility>
56
67#include < QCoreApplication>
78#include < QEvent>
89#include < QKeyEvent>
910#include < QMouseEvent>
1011#include < QPainter>
12+ #include < QRadialGradient>
1113#include < QWheelEvent>
1214
1315namespace safecrowd ::application {
@@ -16,8 +18,9 @@ namespace {
1618constexpr double kViewportPadding = 32.0 ;
1719constexpr double kVelocityIndicatorSeconds = 0.75 ;
1820constexpr double kAgentMarkerRadius = 5.0 ;
19- constexpr int kHotspotMinAlpha = 42 ;
20- constexpr int kHotspotMaxAlpha = 156 ;
21+ constexpr double kDefaultHotspotCellSize = 1.5 ;
22+ constexpr int kHotspotMinCoreAlpha = 72 ;
23+ constexpr int kHotspotMaxCoreAlpha = 190 ;
2124
2225} // namespace
2326
@@ -205,18 +208,39 @@ void SimulationCanvasWidget::drawHotspotOverlay(QPainter& painter, const LayoutC
205208 painter.save ();
206209 painter.setPen (Qt::NoPen);
207210 painter.setCompositionMode (QPainter::CompositionMode_SourceOver);
211+ QPainterPath walkableClip;
212+ for (const auto & zone : layout_.zones ) {
213+ walkableClip.addPath (layoutCanvasPolygonPath (zone.area , transform));
214+ }
215+ if (!walkableClip.isEmpty ()) {
216+ painter.setClipPath (walkableClip);
217+ }
218+
208219 for (const auto & hotspot : hotspotOverlay_) {
209220 if (hotspot.agentCount == 0 ) {
210221 continue ;
211222 }
212- const auto topLeft = transform.map ({.x = hotspot.cellMin .x , .y = hotspot.cellMax .y });
213- const auto bottomRight = transform.map ({.x = hotspot.cellMax .x , .y = hotspot.cellMin .y });
214- const QRectF cellRect (topLeft, bottomRight);
215223 const auto intensity = static_cast <double >(hotspot.agentCount ) / static_cast <double >(maxAgentCount);
216- const auto alpha = kHotspotMinAlpha
217- + static_cast <int >((kHotspotMaxAlpha - kHotspotMinAlpha ) * intensity);
218- painter.setBrush (QColor (220 , 38 , 38 , std::clamp (alpha, kHotspotMinAlpha , kHotspotMaxAlpha )));
219- painter.drawRoundedRect (cellRect.normalized (), 6.0 , 6.0 );
224+ const auto center = transform.map (hotspot.center );
225+ const auto cellWidth = hotspot.cellMax .x > hotspot.cellMin .x
226+ ? hotspot.cellMax .x - hotspot.cellMin .x
227+ : kDefaultHotspotCellSize ;
228+ const auto cellHeight = hotspot.cellMax .y > hotspot.cellMin .y
229+ ? hotspot.cellMax .y - hotspot.cellMin .y
230+ : kDefaultHotspotCellSize ;
231+ const auto sourceRadiusWorld = std::max (cellWidth, cellHeight) * (1.2 + (0.85 * std::sqrt (intensity)));
232+ const auto radiusAnchor = transform.map ({.x = hotspot.center .x + sourceRadiusWorld, .y = hotspot.center .y });
233+ const auto radius = std::max (12.0 , std::hypot (radiusAnchor.x () - center.x (), radiusAnchor.y () - center.y ()));
234+ const auto coreAlpha = kHotspotMinCoreAlpha
235+ + static_cast <int >((kHotspotMaxCoreAlpha - kHotspotMinCoreAlpha ) * intensity);
236+
237+ QRadialGradient gradient (center, radius);
238+ gradient.setColorAt (0.0 , QColor (185 , 28 , 28 , std::clamp (coreAlpha, kHotspotMinCoreAlpha , kHotspotMaxCoreAlpha )));
239+ gradient.setColorAt (0.28 , QColor (220 , 38 , 38 , static_cast <int >(coreAlpha * 0.62 )));
240+ gradient.setColorAt (0.58 , QColor (249 , 115 , 22 , static_cast <int >(coreAlpha * 0.28 )));
241+ gradient.setColorAt (1.0 , QColor (249 , 115 , 22 , 0 ));
242+ painter.setBrush (gradient);
243+ painter.drawEllipse (center, radius, radius);
220244 }
221245 painter.restore ();
222246}
0 commit comments