void MPointCreator::ProcessCurve(const SimpleLine& rCurve,
                                 const Interval<Instant> TimeInterval,
                                 double dCurveLength)
{
    double dLength = dCurveLength < 0.0 ?
                           MMUtil::CalcLengthCurve(&rCurve, m_dNetworkScale) :
                           dCurveLength;
    if (AlmostEqual(dLength, 0.0))
    {
        AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval,
                                                rCurve.StartPoint(),
                                                rCurve.EndPoint()));
        m_pResMPoint->Add(*pUPoint);
        return;
    }

    DateTime Duration = TimeInterval.end - TimeInterval.start;
    Duration.Abs();

    const bool bStartsSmaller = rCurve.GetStartSmaller();

    Instant TimeStart(TimeInterval.start);

    const int nHalfSegments = rCurve.Size();
    if (nHalfSegments <= 0)
        return;

    assert(nHalfSegments % 2 == 0);

    LRS lrs(bStartsSmaller ? 0.0 : rCurve.Length(), 0);
    int lrsPosAkt = 0;
    if (!const_cast<SimpleLine&>(rCurve).Get(lrs, lrsPosAkt))
    {
        assert(false);
        return;
    }

    LRS lrsAkt;
    rCurve.Get(lrsPosAkt, lrsAkt);
    HalfSegment hs;
    rCurve.Get(lrsAkt.hsPos, hs);

    double dLengthHS = MMUtil::CalcDistance(hs.GetLeftPoint(),
                                            hs.GetRightPoint(),
                                            m_dNetworkScale);
    DateTime TimeEnd = TimeStart +
                       DateTime(datetime::durationtype,
                                    (uint64_t)(((Duration.millisecondsToNull()
                                                 / dLength) * dLengthHS) + .5));

    Interval<Instant> TimeIntervalAkt(TimeStart, TimeEnd,
                                      true, TimeStart == TimeEnd);

    Point Pt1(false);
    Point Pt2(false);

    if (const_cast<SimpleLine&>(rCurve).StartsSmaller())
    {
        Pt1 = hs.GetDomPoint();
        Pt2 = hs.GetSecPoint();
    }
    else
    {
        Pt1 = hs.GetSecPoint();
        Pt2 = hs.GetDomPoint();
    }

    AttributePtr<UPoint> pUPoint(new UPoint(TimeIntervalAkt, Pt1, Pt2));
    m_pResMPoint->Add(*pUPoint);

    TimeStart = TimeEnd;

    if (bStartsSmaller)
        ++lrsPosAkt;
    else
        --lrsPosAkt;

    while (lrsPosAkt >= 0 && lrsPosAkt < nHalfSegments / 2)
    {
        rCurve.Get(lrsPosAkt, lrsAkt);
        rCurve.Get(lrsAkt.hsPos, hs);

        double dLengthHS = MMUtil::CalcDistance(hs.GetLeftPoint(),
                                                hs.GetRightPoint(),
                                                m_dNetworkScale);

        DateTime TimeEnd = TimeStart +
                           DateTime(datetime::durationtype,
                                    (uint64_t)(((Duration.millisecondsToNull()
                                                 / dLength) * dLengthHS) + .5));

        Interval<Instant> TimeIntervalAkt(TimeStart, TimeEnd,
                                          true, TimeStart == TimeEnd);

        if (AlmostEqual(Pt2, hs.GetDomPoint()))
        {
            Pt1 = hs.GetDomPoint();
            Pt2 = hs.GetSecPoint();
        }
        else
        {
            Pt1 = hs.GetSecPoint();
            Pt2 = hs.GetDomPoint();
        }

        /*if (AlmostEqual(Pt2, rCurve.EndPoint()))
            TimeStart = TimeInterval.end;*/

        AttributePtr<UPoint> pUPoint(new UPoint(TimeIntervalAkt, Pt1, Pt2));
        m_pResMPoint->Add(*pUPoint);

        TimeStart = TimeEnd;

        if (bStartsSmaller)
            ++lrsPosAkt;
        else
            --lrsPosAkt;
    }
}
void MPointCreator::ProcessPoints(
                         const MHTRouteCandidate::PointData& rData1,
                         const MHTRouteCandidate::RouteSegment& rSegment1,
                         const MHTRouteCandidate::PointData& rData2,
                         std::vector<const SimpleLine*>& vecCurvesBetweenPoints)
{
    Point Pt1(false);
    if (rData1.GetPointProjection() != NULL)
        Pt1 = *(rData1.GetPointProjection());
    else
        Pt1 = rData1.GetPointGPS();

    Point Pt2(false);
    if (rData2.GetPointProjection() != NULL)
        Pt2 = *(rData2.GetPointProjection());
    else
        Pt2 = rData2.GetPointGPS();

    if (AlmostEqual(Pt1, Pt2))
    {
        Interval<Instant> TimeInterval(rData1.GetTime(),
                                       rData2.GetTime(),
                                       true,
                                       rData1.GetTime() == rData2.GetTime());

        AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval, Pt1, Pt1));
        m_pResMPoint->Add(*pUPoint);

        assert(vecCurvesBetweenPoints.size() == 0);
    }
    else
    {
        const shared_ptr<IMMNetworkSection>& pSection1 = rData1.GetSection();
        const shared_ptr<IMMNetworkSection>& pSection2 = rData2.GetSection();

        if (pSection1 == NULL || !pSection1->IsDefined() ||
            pSection2 == NULL || !pSection2->IsDefined())
        {
            // at least one point is offroad

            Interval<Instant> TimeInterval(
                                          rData1.GetTime(),
                                          rData2.GetTime(),
                                          true,
                                          rData1.GetTime() == rData2.GetTime());

            AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval, Pt1, Pt2));
            m_pResMPoint->Add(*pUPoint);
        }
        else if (pSection1 == pSection2) // Same section
        {
            const SimpleLine* pSectionCurve = pSection1->GetCurve();

            AttributePtr<SimpleLine> pSubline(new SimpleLine(0));
            MMUtil::SubLine(pSectionCurve,
                            Pt1,
                            Pt2,
                            pSection1->GetCurveStartsSmaller(),
                            m_dNetworkScale,
                            *pSubline);

            if (pSubline->IsDefined() &&
                pSubline->StartPoint().IsDefined() &&
                pSubline->EndPoint().IsDefined())
            {
                Interval<Instant> TimeInterval(
                                          rData1.GetTime(),
                                          rData2.GetTime(),
                                          true,
                                          rData1.GetTime() == rData2.GetTime());

                //assert(AlmostEqual(Pt1, pSubline->StartPoint()));

                ProcessCurve(*pSubline, TimeInterval);
            }
        }
        else // different sections
        {
            // Calculate total length of curves

            const SimpleLine* pSection1Curve = pSection1->GetCurve();

            AttributePtr<SimpleLine> pSubline1(new SimpleLine(0));
            MMUtil::SubLine(pSection1Curve,
                            Pt1,
                            !rSegment1.HasUTurn() ? pSection1->GetEndPoint() :
                                                    pSection1->GetStartPoint(),
                            pSection1->GetCurveStartsSmaller(),
                            m_dNetworkScale,
                            *pSubline1);

            double dLenCurve1 = MMUtil::CalcLengthCurve(pSubline1.get(),
                                                        m_dNetworkScale);


            const SimpleLine* pSection2Curve = pSection2->GetCurve();

            AttributePtr<SimpleLine> pSubline2(new SimpleLine(0));
            MMUtil::SubLine(pSection2Curve,
                            pSection2->GetStartPoint(),
                            Pt2,
                            pSection2->GetCurveStartsSmaller(),
                            m_dNetworkScale,
                            *pSubline2);

            double dLenCurve2 = MMUtil::CalcLengthCurve(pSubline2.get(),
                                                        m_dNetworkScale);


            double dLength = dLenCurve1 + dLenCurve2;


            const size_t nCurves = vecCurvesBetweenPoints.size();
            for (size_t i = 0; i < nCurves; ++i)
            {
                dLength += MMUtil::CalcLengthCurve(vecCurvesBetweenPoints[i],
                                                   m_dNetworkScale);
            }

            // Total time
            DateTime Duration = rData2.GetTime() - rData1.GetTime();
            Duration.Abs();

            // Process first curve

            DateTime TimeEnd(rData1.GetTime());

            if (!pSubline1 ||
                AlmostEqual(dLenCurve1, 0.0))
            {
                Interval<Instant> TimeInterval(rData1.GetTime(),
                                               TimeEnd,
                                               true, true);
                AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval,
                                                        Pt1, Pt1));
                m_pResMPoint->Add(*pUPoint);
            }
            else
            {
                TimeEnd = rData1.GetTime() +
                           DateTime(datetime::durationtype,
                                    (uint64_t)(((Duration.millisecondsToNull()
                                                / dLength) * dLenCurve1) + .5));
                Interval<Instant> TimeInterval(rData1.GetTime(),
                                               TimeEnd,
                                               true,
                                               rData1.GetTime() == TimeEnd);
                ProcessCurve(*pSubline1, TimeInterval, dLenCurve1);
            }

            // Process curves in between

            for (size_t i = 0; i < nCurves; ++i)
            {
                const SimpleLine* pCurve = vecCurvesBetweenPoints[i];
                if (pCurve == NULL)
                    continue;

                double dLenCurve = MMUtil::CalcLengthCurve(pCurve,
                                                           m_dNetworkScale);
                if (AlmostEqual(dLenCurve, 0.0))
                    continue;

                DateTime TimeStart = TimeEnd;
                TimeEnd = TimeStart +
                          DateTime(datetime::durationtype,
                                    (uint64_t)(((Duration.millisecondsToNull()
                                                / dLength) * dLenCurve) + .5));

                Interval<Instant> TimeInterval(TimeStart,
                                               TimeEnd,
                                               true, false);

                ProcessCurve(*pCurve, TimeInterval, dLenCurve);
            }

            // Process last curve

            if (!pSubline2 ||
                AlmostEqual(dLenCurve2, 0.0))
            {
                DateTime TimeStart = TimeEnd;
                TimeEnd = rData2.GetTime();
                Interval<Instant> TimeInterval(TimeStart,
                                               TimeEnd,
                                               true, true);
                AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval,
                                                        Pt2, Pt2));
                m_pResMPoint->Add(*pUPoint);
            }
            else
            {
                assert(TimeEnd.millisecondsToNull() <=
                       rData2.GetTime().millisecondsToNull());
                DateTime TimeStart = TimeEnd;
                TimeEnd = rData2.GetTime();
                Interval<Instant> TimeInterval(TimeStart,
                                               TimeEnd,
                                               true, false);
                ProcessCurve(*pSubline2, TimeInterval, dLenCurve2);
            }
        }
    }
}