Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
230
libs/map/track.cpp
Normal file
230
libs/map/track.cpp
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
#include "map/track.hpp"
|
||||
|
||||
#include "map/bookmark_helpers.hpp"
|
||||
#include "map/user_mark_id_storage.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
#include "geometry/rect_intersect.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
Track::Track(kml::TrackData && data)
|
||||
: Base(data.m_id == kml::kInvalidTrackId ? UserMarkIdStorage::Instance().GetNextTrackId() : data.m_id)
|
||||
, m_data(std::move(data))
|
||||
{
|
||||
m_data.m_id = GetId();
|
||||
CHECK(m_data.m_geometry.IsValid(), ());
|
||||
}
|
||||
|
||||
void Track::CacheDataForInteraction() const
|
||||
{
|
||||
m_interactionData = InteractionData();
|
||||
m_interactionData->m_lengths = GetLengthsImpl();
|
||||
m_interactionData->m_limitRect = GetLimitRectImpl();
|
||||
}
|
||||
|
||||
std::vector<Track::Lengths> Track::GetLengthsImpl() const
|
||||
{
|
||||
double distance = 0;
|
||||
std::vector<Lengths> lengths;
|
||||
for (auto const & line : m_data.m_geometry.m_lines)
|
||||
{
|
||||
Lengths lineLengths;
|
||||
lineLengths.emplace_back(distance);
|
||||
for (size_t j = 1; j < line.size(); ++j)
|
||||
{
|
||||
auto const & pt1 = line[j - 1].GetPoint();
|
||||
auto const & pt2 = line[j].GetPoint();
|
||||
distance += mercator::DistanceOnEarth(pt1, pt2);
|
||||
lineLengths.emplace_back(distance);
|
||||
}
|
||||
lengths.emplace_back(std::move(lineLengths));
|
||||
}
|
||||
return lengths;
|
||||
}
|
||||
|
||||
m2::RectD Track::GetLimitRectImpl() const
|
||||
{
|
||||
m2::RectD limitRect;
|
||||
for (auto const & line : m_data.m_geometry.m_lines)
|
||||
for (auto const & pt : line)
|
||||
limitRect.Add(pt.GetPoint());
|
||||
return limitRect;
|
||||
}
|
||||
|
||||
bool Track::HasAltitudes() const
|
||||
{
|
||||
bool hasNonDefaultAltitude = false;
|
||||
|
||||
for (auto const & line : m_data.m_geometry.m_lines)
|
||||
{
|
||||
for (auto const & pt : line)
|
||||
{
|
||||
if (pt.GetAltitude() == geometry::kInvalidAltitude)
|
||||
return false;
|
||||
if (!hasNonDefaultAltitude && pt.GetAltitude() != geometry::kDefaultAltitudeMeters)
|
||||
hasNonDefaultAltitude = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasNonDefaultAltitude;
|
||||
}
|
||||
|
||||
std::string Track::GetName() const
|
||||
{
|
||||
return GetPreferredBookmarkStr(m_data.m_name);
|
||||
}
|
||||
|
||||
void Track::SetName(std::string const & name)
|
||||
{
|
||||
kml::SetDefaultStr(m_data.m_name, name);
|
||||
}
|
||||
|
||||
std::string Track::GetDescription() const
|
||||
{
|
||||
return GetPreferredBookmarkStr(m_data.m_description);
|
||||
}
|
||||
|
||||
void Track::setData(kml::TrackData const & data)
|
||||
{
|
||||
m_isDirty = true;
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
m2::RectD Track::GetLimitRect() const
|
||||
{
|
||||
if (m_interactionData)
|
||||
return m_interactionData->m_limitRect;
|
||||
return GetLimitRectImpl();
|
||||
}
|
||||
|
||||
double Track::GetLengthMeters() const
|
||||
{
|
||||
return GetStatistics().m_length;
|
||||
}
|
||||
|
||||
double Track::GetLengthMetersImpl(size_t lineIndex, size_t ptIndex) const
|
||||
{
|
||||
if (!m_interactionData)
|
||||
CacheDataForInteraction();
|
||||
auto const & lineLengths = m_interactionData->m_lengths[lineIndex];
|
||||
return lineLengths[ptIndex];
|
||||
}
|
||||
|
||||
void Track::UpdateSelectionInfo(m2::RectD const & touchRect, TrackSelectionInfo & info) const
|
||||
{
|
||||
if (m_interactionData && !m_interactionData->m_limitRect.IsIntersect(touchRect))
|
||||
return;
|
||||
|
||||
for (size_t lineIndex = 0; lineIndex < m_data.m_geometry.m_lines.size(); ++lineIndex)
|
||||
{
|
||||
auto const & line = m_data.m_geometry.m_lines[lineIndex];
|
||||
for (size_t ptIndex = 0; ptIndex + 1 < line.size(); ++ptIndex)
|
||||
{
|
||||
auto pt1 = line[ptIndex].GetPoint();
|
||||
auto pt2 = line[ptIndex + 1].GetPoint();
|
||||
if (!m2::Intersect(touchRect, pt1, pt2))
|
||||
continue;
|
||||
|
||||
m2::ParametrizedSegment<m2::PointD> seg(pt1, pt2);
|
||||
auto const closestPoint = seg.ClosestPointTo(touchRect.Center());
|
||||
auto const squaredDist = closestPoint.SquaredLength(touchRect.Center());
|
||||
if (squaredDist >= info.m_squareDist)
|
||||
continue;
|
||||
|
||||
info.m_squareDist = squaredDist;
|
||||
info.m_trackId = m_data.m_id;
|
||||
info.m_trackPoint = closestPoint;
|
||||
|
||||
auto const segDistInMeters = mercator::DistanceOnEarth(line[ptIndex].GetPoint(), closestPoint);
|
||||
info.m_distFromBegM = segDistInMeters + GetLengthMetersImpl(lineIndex, ptIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
df::DepthLayer Track::GetDepthLayer() const
|
||||
{
|
||||
return df::DepthLayer::UserLineLayer;
|
||||
}
|
||||
|
||||
size_t Track::GetLayerCount() const
|
||||
{
|
||||
return m_data.m_layers.size();
|
||||
}
|
||||
|
||||
dp::Color Track::GetColor(size_t layerIndex) const
|
||||
{
|
||||
CHECK_LESS(layerIndex, m_data.m_layers.size(), ());
|
||||
return dp::Color(m_data.m_layers[layerIndex].m_color.m_rgba);
|
||||
}
|
||||
|
||||
void Track::SetColor(dp::Color color)
|
||||
{
|
||||
m_isDirty = true;
|
||||
m_data.m_layers[0].m_color.m_rgba = color.GetRGBA();
|
||||
}
|
||||
|
||||
float Track::GetWidth(size_t layerIndex) const
|
||||
{
|
||||
CHECK_LESS(layerIndex, m_data.m_layers.size(), ());
|
||||
return static_cast<float>(m_data.m_layers[layerIndex].m_lineWidth);
|
||||
}
|
||||
|
||||
float Track::GetDepth(size_t layerIndex) const
|
||||
{
|
||||
return layerIndex * 10;
|
||||
}
|
||||
|
||||
void Track::ForEachGeometry(GeometryFnT && fn) const
|
||||
{
|
||||
for (auto const & line : m_data.m_geometry.m_lines)
|
||||
{
|
||||
std::vector<m2::PointD> points;
|
||||
points.reserve(line.size());
|
||||
for (auto const & pt : line)
|
||||
points.push_back(pt.GetPoint());
|
||||
|
||||
fn(std::move(points));
|
||||
}
|
||||
}
|
||||
|
||||
void Track::Attach(kml::MarkGroupId groupId)
|
||||
{
|
||||
ASSERT_EQUAL(m_groupID, kml::kInvalidMarkGroupId, ());
|
||||
m_groupID = groupId;
|
||||
}
|
||||
|
||||
void Track::Detach()
|
||||
{
|
||||
m_groupID = kml::kInvalidMarkGroupId;
|
||||
}
|
||||
|
||||
kml::MultiGeometry::LineT Track::GetGeometry() const
|
||||
{
|
||||
kml::MultiGeometry::LineT geometry;
|
||||
for (auto const & line : m_data.m_geometry.m_lines)
|
||||
for (size_t i = 0; i < line.size(); ++i)
|
||||
geometry.emplace_back(line[i]);
|
||||
return geometry;
|
||||
}
|
||||
|
||||
TrackStatistics Track::GetStatistics() const
|
||||
{
|
||||
if (!m_trackStatistics.has_value())
|
||||
m_trackStatistics = TrackStatistics(m_data.m_geometry);
|
||||
return m_trackStatistics.value();
|
||||
}
|
||||
|
||||
std::optional<ElevationInfo> Track::GetElevationInfo() const
|
||||
{
|
||||
if (!HasAltitudes())
|
||||
return std::nullopt;
|
||||
if (!m_elevationInfo)
|
||||
m_elevationInfo = ElevationInfo(GetData().m_geometry.m_lines);
|
||||
return m_elevationInfo;
|
||||
}
|
||||
|
||||
double Track::GetDurationInSeconds() const
|
||||
{
|
||||
return GetStatistics().m_duration;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue