Exemplo n.º 1
0
void MoveNodeInteraction::recurseAddNodes(Feature* F)
{
    if (Node* Pt = CAST_NODE(F))
    {
        Moving.push_back(Pt);
    }
    else if (Way* R = CAST_WAY(F)) {
        if (!g_Merk_Segment_Mode) {
            for (int j=0; j<R->size(); ++j)
                if (std::find(Moving.begin(),Moving.end(),R->get(j)) == Moving.end()) {
                    Moving.push_back(R->getNode(j));
                }
        } else {
            for (int j=R->bestSegment(); j<=R->bestSegment()+1; ++j)
                if (std::find(Moving.begin(),Moving.end(),R->get(j)) == Moving.end()) {
                    Moving.push_back(R->getNode(j));
                }
        }
        addToNoSnap(R);
    }
    else if (Relation* L = CAST_RELATION(F)) {
        for (int j=0; j<L->size(); ++j)
            recurseAddNodes(L->get(j));
        addToNoSnap(L);
    }
}
Exemplo n.º 2
0
Node * Node::fromXML(Document* d, Layer* L, QXmlStreamReader& stream)
{
    qreal Lat = stream.attributes().value("lat").toString().toDouble();
    qreal Lon = stream.attributes().value("lon").toString().toDouble();

    QString sid = (stream.attributes().hasAttribute("id") ? stream.attributes().value("id").toString() : stream.attributes().value("xml:id").toString());
    IFeature::FId id(IFeature::Point, sid.toLongLong());
    Node* Pt = CAST_NODE(d->getFeature(id));
    if (!Pt) {
        Pt = g_backend.allocNode(L, Coord(Lon,Lat));
        Pt->setId(id);
        L->add(Pt);
        Feature::fromXML(stream, Pt);
    } else {
        Feature::fromXML(stream, Pt);
        if (Pt->layer() != L) {
            Pt->layer()->remove(Pt);
            L->add(Pt);
        }
        Pt->setPosition(Coord(Lon, Lat));
    }

    stream.readNext();
    while(!stream.atEnd() && !stream.isEndElement()) {
        if (stream.name() == "tag") {
            Pt->setTag(stream.attributes().value("k").toString(), stream.attributes().value("v").toString());
            stream.readNext();
        }

       stream.readNext();
    }

    return Pt;
}
void CreateSingleWayInteraction::paintEvent(QPaintEvent* anEvent, QPainter& thePainter)
{
    if (theRoad && (!theRoad->layer() || theRoad->isDeleted())) { // The road was begon and then undoed. Restarting....
        HaveFirst = false;
        theRoad = NULL;
        Creating = false;
        view()->setInteracting(false);
    }

    if (HaveFirst)
    {
        QPointF PreviousPoint;
        if (theRoad && theRoad->size() && !Prepend)
            PreviousPoint = COORD_TO_XY(CAST_NODE(theRoad->get(theRoad->size()-1))->position());
        else
            PreviousPoint = COORD_TO_XY(FirstPoint);
        QBrush SomeBrush(QColor(0xff,0x77,0x11,128));
        QPen TP(SomeBrush,qBound(3, int(view()->pixelPerM()*4+2), 10));
        ::draw(thePainter,TP,Feature::UnknownDirection, PreviousPoint,LastCursor ,4 ,view()->projection());

        Coord NewPoint = XY_TO_COORD(LastCursor);
        const qreal distance = FirstPoint.distanceFrom(NewPoint);

        QString distanceTag;
        if (distance < 1.0)
            distanceTag = QString("%1 m").arg(int(distance * 1000));
        else
            distanceTag = QString("%1 km").arg(distance, 0, 'f', 3);

        thePainter.drawText(LastCursor + QPointF(10,-10), distanceTag);
    }
    FeatureSnapInteraction::paintEvent(anEvent,thePainter);
}
Exemplo n.º 4
0
void MoveNodeInteraction::snapMousePressEvent(QMouseEvent * event, Feature* aLast)
{
    QList<Feature*> sel;
    if (view()->isSelectionLocked()) {
        if (theMain->properties()->selection(0))
            sel.append(theMain->properties()->selection(0));
        else
            sel.append(aLast);
    } else {
        if (aLast) {
            if (theMain->properties()->selection().size() && !M_PREFS->getSeparateMoveMode())
                sel = theMain->properties()->selection();
            else
                sel.append(aLast);
        }
    }
    HasMoved = false;
    clearNoSnap();
    Moving.clear();
    OriginalPosition.clear();
    StartDragPosition = XY_TO_COORD(event->pos());
    if (sel.size() == 1) {
        if (Node* Pt = CAST_NODE(sel[0])) {
            StartDragPosition = Pt->position();
            Moving.push_back(Pt);
        } else
            recurseAddNodes(sel[0]);
    } else {
        for (int i=0; i<sel.size(); i++) {
            recurseAddNodes(sel[i]);
        }
    }

    for (int i=0; i<Moving.size(); ++i)
    {
        OriginalPosition.push_back(Moving[i]->position());
        addToNoSnap(Moving[i]);
    }
    Virtual = false;
    theList = new CommandList;
}
Exemplo n.º 5
0
bool TrackLayer::toXML(QXmlStreamWriter& stream, bool asTemplate, QProgressDialog * progress)
{
    bool OK = true;
    if (asTemplate)
        return OK;

    stream.writeStartElement(metaObject()->className());
    Layer::toXML(stream, asTemplate, progress);

    stream.writeStartElement("gpx");
    stream.writeAttribute("version", "1.1");
    stream.writeAttribute("creator", "Merkaartor");
    stream.writeAttribute("xmlns", "http://www.topografix.com/GPX/1/1");

    QList<Node*>	waypoints;
    QList<TrackSegment*>	segments;
    QList<MapFeaturePtr>::iterator it;
    for(it = p->Features.begin(); it != p->Features.end(); it++) {
        if (TrackSegment* S = CAST_SEGMENT(*it))
            segments.push_back(S);
        if (Node* P = CAST_NODE(*it))
            if (!P->tagValue("_waypoint_","").isEmpty())
                waypoints.push_back(P);
    }

    for (int i=0; i < waypoints.size(); ++i) {
        waypoints[i]->toGPX(stream, progress, "wpt");
    }

    stream.writeStartElement("trk");
    for (int i=0; i < segments.size(); ++i)
        segments[i]->toXML(stream, progress);
    stream.writeEndElement();

    stream.writeEndElement(); //gpx
    stream.writeEndElement();

    return OK;
}
Exemplo n.º 6
0
void PropertiesDock::switchUi()
{
    if (CurrentTagView)
        M_PREFS->setTagListFirstColumnWidth(qMax(CurrentTagView->columnWidth(0), 20));

    if (FullSelection.size() == 0)
        switchToNoUi();
    else if (FullSelection.size() == 1)
    {
        if (FullSelection[0]->isVirtual())
            switchToNoUi();
        else if (CAST_NODE(FullSelection[0]))
            switchToNodeUi();
        else if (CAST_WAY(FullSelection[0]))
            switchToWayUi();
        else if (CAST_RELATION(FullSelection[0]))
            switchToRelationUi();
        else
            switchToNoUi();
    }
    else
        switchToMultiUi();
    resetValues();
}
Exemplo n.º 7
0
void PropertiesDock::checkMenuStatus()
{
    bool IsPoint = false;
    bool IsRoad = false;
    bool IsRelation = false;
    bool IsParentRoad = false;
    bool IsParentRoadInner = false;
    bool IsParentRelation = false;
    bool IsParentArea = false;
    bool IsOpenStreetBug = false;
    int NumRoads = 0;
    int NumCommitableFeature = 0;
    int NumPoints = 0;
    int NumRelation = 0;
    int NumRelationChild = 0;
    int NumAreas = 0;
    int NumParents = 0;
    int NumChildren = 0;
    int NumIncomplete = 0;
    if (Selection.size() == 1)
    {
        IsPoint = CAST_NODE(Selection[0]) != 0;
        IsRoad = CAST_WAY(Selection[0]) != 0;
        IsRelation = CAST_RELATION(Selection[0]) != 0;
        IsParentRoad = IsPoint && isChildOfSingleRoad(Selection[0]);
        IsParentRoadInner = IsPoint && isChildOfSingleRoadInner(Selection[0]);
        IsParentRelation = isChildOfSingleRelation(Selection[0]);
        IsParentArea = isChildOfArea(Selection[0]);
        IsOpenStreetBug = isChildOfArea(Selection[0]);
        IsOpenStreetBug = IsPoint && (Selection[0]->id().type & IFeature::Special);
    }
    for (int i=0; i<Selection.size(); ++i)
    {
        if (Selection[i]->sizeParents())
            ++NumParents;
        if (Selection[i]->size())
            ++NumChildren;
        if (Selection[i]->notEverythingDownloaded())
            ++NumIncomplete;

        if (CAST_NODE(Selection[i]))
            ++NumPoints;
        if (Way* R = dynamic_cast<Way*>(Selection[i]))
        {
            if (R->area() > 0.0)
            {
                ++NumAreas;
            }
            else
            {
                ++NumRoads;
            }
        }
        if (CAST_RELATION(Selection[i]))
            ++NumRelation;
        if (isChildOfRelation(Selection[i]))
            ++NumRelationChild;

        if (!Selection[i]->isUploadable() && !Selection[i]->isSpecial())
            ++NumCommitableFeature;
    }
#ifndef _MOBILE
    Main->ui->createRelationAction->setEnabled(Selection.size());
    Main->ui->editRemoveAction->setEnabled(Selection.size());
    Main->ui->editMoveAction->setEnabled(true);
    Main->ui->editReverseAction->setEnabled(IsRoad || NumAreas + NumRoads > 0);
    Main->ui->roadAddStreetNumbersAction->setEnabled(NumRoads >= 1);
    Main->ui->roadJoinAction->setEnabled(NumRoads >= 1 && canJoinRoads(this));
    Main->ui->roadCreateJunctionAction->setEnabled(NumRoads > 1 && canCreateJunction(this));
    Main->ui->roadSplitAction->setEnabled((IsParentRoadInner && !IsParentArea) || (NumRoads && NumPoints) || (NumAreas && NumPoints > 1));
    Main->ui->roadBreakAction->setEnabled(IsParentRoadInner || ((NumRoads == 1 || NumAreas == 1) && NumPoints) || (NumRoads > 1 && canBreakRoads(this)));
    Main->ui->roadSimplifyAction->setEnabled(IsRoad || NumRoads > 0 || NumAreas > 0);
    Main->ui->roadSubdivideAction->setEnabled((NumRoads + NumAreas) == 1 && (!NumPoints || NumPoints == 2) && canSubdivideRoad(this));
    Main->ui->roadAxisAlignAction->setEnabled((NumRoads + NumAreas) > 0 || (NumRelation > 0 && canAxisAlignRoads(this)));
    Main->ui->areaJoinAction->setEnabled(NumAreas > 1);
    Main->ui->areaSplitAction->setEnabled(NumAreas == 1 && NumPoints == 2 && canSplitArea(this));
    Main->ui->areaTerraceAction->setEnabled(NumAreas == 1 && NumRoads == 0 && canTerraceArea(this));
    Main->ui->featureSelectChildrenAction->setEnabled(NumChildren);
    Main->ui->featureSelectParentsAction->setEnabled(NumParents);
    Main->ui->featureDownloadMissingChildrenAction->setEnabled(NumIncomplete);
    Main->ui->featureDeleteAction->setEnabled((IsPoint || IsRoad || IsRelation) && !Selection[0]->isDirty());
    Main->ui->featureCommitAction->setEnabled(NumCommitableFeature);
    Main->ui->nodeMergeAction->setEnabled(NumPoints > 1);
    Main->ui->nodeAlignAction->setEnabled(NumPoints > 2);
    Main->ui->nodeSpreadAction->setEnabled(NumPoints > 2);
    Main->ui->nodeDetachAction->setEnabled(NumPoints && canDetachNodes(this));
    Main->ui->relationAddMemberAction->setEnabled(NumRelation && Selection.size() > 1);
    Main->ui->relationRemoveMemberAction->setEnabled((NumRelation && Selection.size() > 1 && NumRelationChild) || IsParentRelation);
    Main->ui->relationAddToMultipolygonAction->setEnabled((NumAreas > 1) || (NumAreas >0 && NumRelation == 1));

    Main->ui->editCopyAction->setEnabled(Selection.size());
    Main->clipboardChanged();
#endif
}
Exemplo n.º 8
0
// export
bool ExportGPX::export_(const QList<Feature *>& featList)
{
    QList<Node*>	waypoints;
    QList<TrackSegment*>	segments;
    QList<Layer*>	tracks;
    QList<Way*>	routes;

    if(! IImportExport::export_(featList) ) return false;

    bool OK = true;

    QXmlStreamWriter stream(Device);
    stream.setAutoFormatting(true);
    stream.setAutoFormattingIndent(2);
    stream.writeStartDocument();

    QProgressDialog progress(QApplication::tr("Exporting GPX..."), QApplication::tr("Cancel"), 0, 0);
    progress.setWindowModality(Qt::WindowModal);
    progress.setMaximum(progress.maximum() + featList.count());

    stream.writeStartElement("gpx");
    stream.writeAttribute("version", "1.1");
    stream.writeAttribute("creator", QString("%1 v%2%3").arg(STRINGIFY(PRODUCT)).arg(STRINGIFY(VERSION)).arg(STRINGIFY(REVISION)));
    stream.writeAttribute("xmlns", "http://www.topografix.com/GPX/1/1");

    for (int i=0; i<theFeatures.size(); ++i) {
        if (TrackSegment* S = dynamic_cast<TrackSegment*>(theFeatures[i])) {
            segments.push_back(S);
            if (!tracks.contains(S->layer()))
                tracks.push_back(S->layer());
        } else
        if (Node* P = CAST_NODE(theFeatures[i])) {
            if (!P->tagValue("_waypoint_","").isEmpty())
                waypoints.push_back(P);
            if (!P->tagValue("name","").isEmpty() && !P->sizeParents())
                waypoints.push_back(P);
        } else
        if (Way* R = CAST_WAY(theFeatures[i])) {
            if (R->size())
                routes.push_back(R);
        }
    }

    for (int i=0; i < waypoints.size(); ++i) {
        waypoints[i]->toGPX(stream, &progress, "wpt", true);
    }

    for (int i=0; i < routes.size(); ++i) {
        routes[i]->toGPX(stream, &progress, true);
    }

    for (int i=0; i<tracks.size(); ++i) {
        stream.writeStartElement("trk");
        stream.writeTextElement("name", tracks[i]->name());

        for (int j=0; j < segments.size(); ++j)
            if (tracks[i]->exists(segments[j]))
                segments[j]->toGPX(stream, &progress, true);
        stream.writeEndElement();
    }
    stream.writeEndElement();
    stream.writeEndDocument();

    progress.setValue(progress.maximum());
    if (progress.wasCanceled())
        return false;

    return OK;
}
Exemplo n.º 9
0
void MapRenderer::render(
        QPainter* P,
        QMap<RenderPriority, QSet <Feature*> > theFeatures,
        const RendererOptions& options,
        MapView* aView
)
{
    #ifndef NDEBUG
        QTime Start(QTime::currentTime());
    #endif

    theView = aView;
    theOptions = options;

    QMap<RenderPriority, QSet<Feature*> >::const_iterator itm;
    QSet<Feature*>::const_iterator it;

    bool bgLayerVisible = TEST_RFLAGS(RendererOptions::BackgroundVisible);
    bool fgLayerVisible = TEST_RFLAGS(RendererOptions::ForegroundVisible);
    bool tchpLayerVisible = TEST_RFLAGS(RendererOptions::TouchupVisible);
    bool lblLayerVisible = TEST_RFLAGS(RendererOptions::NamesVisible);

    Way * R = NULL;
    Node * Pt = NULL;
    Relation * RR = NULL;

    QPixmap pix(theView->size());
    thePainter = new QPainter();

    itm = theFeatures.constBegin();
    while (itm != theFeatures.constEnd())
    {
        pix.fill(Qt::transparent);
        thePainter->begin(&pix);
        if (M_PREFS->getUseAntiAlias())
            thePainter->setRenderHint(QPainter::Antialiasing);
        int curLayer = (itm.key()).layer();
        while (itm != theFeatures.constEnd() && (itm.key()).layer() == curLayer)
        {
            for (it = itm.value().constBegin(); it != itm.value().constEnd(); ++it)
            {
                qreal alpha = (*it)->getAlpha();
                thePainter->setOpacity(alpha);

                R = NULL;
                Pt = NULL;
                RR = NULL;

                if (!(R = CAST_WAY(*it)))
                    if (!(Pt = CAST_NODE(*it)))
                        RR = CAST_RELATION(*it);

                if (R) {
                    // If there is painter at the relation level, don't paint at the way level
                    bool draw = true;
                    for (int i=0; i<R->sizeParents(); ++i) {
                        if (!R->getParent(i)->isDeleted() && R->getParent(i)->hasPainter(PixelPerM))
                            draw = false;
                    }
                    if (!draw)
                        continue;
                }

                if (!Pt) {
                    if (bgLayerVisible)
                    {
                        thePainter->save();
                        if (R && R->area() == 0)
                            thePainter->setCompositionMode(QPainter::CompositionMode_DestinationOver);

                        if (R)
                            bglayer.draw(R);
                        else if (Pt)
                            bglayer.draw(Pt);
                        else if (RR)
                            bglayer.draw(RR);

                        thePainter->restore();
                    }
                    if (fgLayerVisible)
                    {
                        thePainter->save();

                        if (R)
                            fglayer.draw(R);
                        else if (Pt)
                            fglayer.draw(Pt);
                        else if (RR)
                            fglayer.draw(RR);

                        thePainter->restore();
                    }
                }
                if (tchpLayerVisible)
                {
                    thePainter->save();

                    if (R)
                        tchuplayer.draw(R);
                    else if (Pt)
                        tchuplayer.draw(Pt);
                    else if (RR)
                        tchuplayer.draw(RR);

                    thePainter->restore();
                }
                if (lblLayerVisible) {
                    thePainter->save();

                    if (R)
                        lbllayer.draw(R);
                    else if (Pt)
                        lbllayer.draw(Pt);
                    else if (RR)
                        lbllayer.draw(RR);

                    thePainter->restore();
                }

                (*it)->draw(*thePainter, aView);
            }
            ++itm;
        }
        thePainter->end();
        P->drawPixmap(0, 0, pix);
#ifndef NDEBUG
    QTime Stop(QTime::currentTime());
    qDebug() << Start.msecsTo(Stop) << "ms";
#endif
    }
}
Exemplo n.º 10
0
bool DirtyListVisit::add(Feature* F)
{
    if (DeletePass) return false;
    if (F->isDeleted()) return false;
    // TODO Needed to add children of updated imported features. Sure there is no advert cases?
    //if (!F->isDirty()) return false;

    // Allow "Force Upload" of OSM objects
    //if (F->hasOSMId()) return false;

    if (Future.willBeErased(F))
        return EraseFromHistory;
    for (int i=0; i<AlreadyAdded.size(); ++i)
        if (AlreadyAdded[i] == F)
            return EraseResponse[i];

    bool x;
    if (Node* Pt = CAST_NODE(F))
    {
        if (Pt->isInteresting())
        {
            if (F->hasOSMId())
                x = updatePoint(Pt);
            else
                x = addPoint(Pt);
            AlreadyAdded.push_back(F);
            EraseResponse.push_back(x);
            return x;
        }
        else
            return EraseFromHistory;
    }
    else if (Way* R = dynamic_cast<Way*>(F))
    {
        for (int i=0; i<R->size(); ++i)
            if (!R->getNode(i)->isVirtual())
                if (!(R->get(i)->hasOSMId()) && notYetAdded(R->get(i)))
                    add(R->get(i));
        if (F->hasOSMId())
            x = updateRoad(R);
        else
            x = addRoad(R);
        AlreadyAdded.push_back(F);
        EraseResponse.push_back(x);
        return x;
    }
    else if (Relation* Rel = dynamic_cast<Relation*>(F))
    {
        for (int i=0; i<Rel->size(); ++i)
            if (!(Rel->get(i)->hasOSMId()) && notYetAdded(Rel->get(i)))
                add(Rel->get(i));
        if (F->hasOSMId())
            x = updateRelation(Rel);
        else
            x = addRelation(Rel);
        AlreadyAdded.push_back(F);
        EraseResponse.push_back(x);
        return x;
    }
    return EraseFromHistory;
}
void CreateSingleWayInteraction::snapMouseMoveEvent(QMouseEvent* ev, Feature* lastSnap)
{
    if (Node* Pt = dynamic_cast<Node*>(lastSnap))
        LastCursor = COORD_TO_XY(Pt);
    else if (Way* R = dynamic_cast<Way*>(lastSnap))
    {
        Coord P(XY_TO_COORD(ev->pos()));
        findSnapPointIndex(R, P);
        LastCursor = COORD_TO_XY(P);
    }
    else if (theRoad && theRoad->size() > 1 && SnapAngle)
    {
        QLineF l1(COORD_TO_XY(theRoad->getNode(theRoad->size()-1)), COORD_TO_XY(theRoad->getNode(theRoad->size()-2)));
        QLineF l2(COORD_TO_XY(theRoad->getNode(theRoad->size()-1)), ev->pos());
        qreal a = l1.angleTo(l2);
        a = qRound(a/SnapAngle) * SnapAngle;
        l2.setAngle(l1.angle() + a);
        LastCursor = l2.p2().toPoint();
    }
    else if (HaveFirst && ParallelMode)
    {
#define CLEAR_DISTANCE 200
        QPointF PreviousPoint;
        if (theRoad && theRoad->size() && !Prepend)
            PreviousPoint = COORD_TO_XY(CAST_NODE(theRoad->get(theRoad->size()-1))->position());
        else
            PreviousPoint = COORD_TO_XY(FirstPoint);

        CoordBox HotZone(XY_TO_COORD(ev->pos()-QPoint(CLEAR_DISTANCE, CLEAR_DISTANCE)),XY_TO_COORD(ev->pos()+QPoint(CLEAR_DISTANCE, CLEAR_DISTANCE)));
        qreal BestDistanceNW = 9999, AngleNW = 0;
        qreal BestDistanceNE = 9999, AngleNE = 0;
        qreal* BestDistance = &BestDistanceNW;
        qreal* BestAngle = &BestDistanceNE;
        qreal curAngle = 666;

        Way* R;
        for (int j=0; j<document()->layerSize(); ++j) {
            QList < Feature* > ret = g_backend.indexFind(document()->getLayer(j), HotZone);
            foreach(Feature* F, ret) {
                if (!(R = CAST_WAY(F)))
                    continue;

                if (R->isHidden())
                    continue;
                if (R->notEverythingDownloaded())
                    continue;

                for (int i=0; i<R->size()-1; ++i)
                {
                    LineF F(COORD_TO_XY(R->getNode(i)),COORD_TO_XY(R->getNode(i+1)));
                    qreal D = F.capDistance(ev->pos());
                    if (D < CLEAR_DISTANCE) {
                        QLineF l(COORD_TO_XY(R->getNode(i)), COORD_TO_XY(R->getNode(i+1)));
                        qreal a = l.angle();
                        if ((a >= 0 && a < 90) || (a < -270 && a >= -360)) {
                            BestDistance = &BestDistanceNE;
                            BestAngle = &AngleNE;
                            curAngle = a;
                        } else if ((a >= 90 && a < 180) || (a < -180 && a >= -270)) {
                            BestDistance = &BestDistanceNW;
                            BestAngle = &AngleNW;
                            curAngle = a;
                        } else if ((a >= 180 && a < 270) || (a < -90 && a >= -180)) {
                            BestDistance = &BestDistanceNE;
                            BestAngle = &AngleNE;
                            curAngle = a - 180;
                        } else if ((a >= 270 && a < 360) || (a < 0 && a >= -90)) {
                            BestDistance = &BestDistanceNW;
                            BestAngle = &AngleNW;
                            curAngle = a - 180;
                        }

                        if (D < *BestDistance) {
                            *BestDistance = D;
                            *BestAngle = curAngle;
                        }
                    }
                }

                qDebug() << BestDistanceNE << BestDistanceNW << AngleNE << AngleNW;
            }
        }

        /* Check if for some reason not a single angle was found. */
        Q_ASSERT(curAngle >= -360 && curAngle <= 360);

        QLineF l(PreviousPoint, ev->pos());
        qreal a = l.angle();
        if ((a >= 0 && a < 90) || (a < -270 && a >= -360)) {
            if (BestDistanceNE < 9999)
                a = AngleNE;
        } else if ((a >= 90 && a < 180) || (a < -180 && a >= -270)) {
            if (BestDistanceNW < 9999)
                a = AngleNW;
        } else if ((a >= 180 && a < 270) || (a < -90 && a >= -180)) {
            if (BestDistanceNE < 9999)
                a = AngleNE - 180;
        } else if ((a >= 270 && a < 360) || (a < 0 && a >= -90)) {
            if (BestDistanceNW < 9999)
                a = AngleNW - 180;
        }
        l.setAngle(a);
        LastCursor = l.p2().toPoint();
    } else