Osmdroid - Marker - increase selection area to get the InfoWindow - osmdroid

When selecting a Marker an InfoWindow pops up.
Sometimes the selection of a Marker is difficult. Especially when the map is rotating in the direction of navigation.
How can I increase the 'touch circle' so that selection is easier?
Update: I have to change the hitTest() for the Marker by subclassing.
I would like to check whether the 'hit' (or touch) was within a circle of X pixels around the point of the Marker. The icon will rotate while I navigate, so I guess I don't use the icon.
How can I do that?
public boolean hitTest(final MotionEvent event, final MapView mapView){
final Projection pj = mapView.getProjection();
pj.toPixels(mPosition, mPositionPixels);
// Does mPositionPixels contains the x, y of the Marker?
// Should I draw a Rect around this point, or could it be a circle?
// How can I check whether the event.getX(), event.getY() is a hit?
return hit;
}

Method proposed by spy is feasible.
You can also create your icon bitmap with an area of transparent pixels around. This is a very simple way to increase its touch area.

I believe #Mker would say, extend the Marker class and override the method hitTest. That is used for the Marker itself. I'm not sure if you can change this for the InfoWindow itself.

Related

Qt QGraphicView and QGraphicScene mouse position

I have project which display inner structure of ELF binary files. I use QGraphicsView and QGraphicsScene. So I can display blocks on graphics scene, but I need after mouse click on single block display content of this block. I am trying use function:
void MainWindow::mousePressEvent(QMouseEvent* event)
{
ui->textEdit->append(QString("x = %1, y = %2").arg(event->Pos().x()).arg(event->Pos().y()));
}
But position is tracking in whole window. Problem is, that width and height of window is dynamical and height of QGraphicsScene may be greater than window's. So I can't track single block.
I tryed some function like:
mapFromScene, mapToScene, mapFromGlobal, ... but I don't know, how theese functions works, but position what I get wasn't right.
It occurred to me that position should be calculated by scrollbar of QGraphicalView and size of window, but it's hard to calculated precisely and it's not correct solution.
Some idea, how get true position on graphic scene? Thanks for any help.
QGraphics, like other graphics frameworks, uses multiple coordinate systems and you need to consider which system you're working in when dealing with coordinates.
We can think of a QGraphicsSceneas a world, within which there are objects that are represented by QGraphicsItems ( or QGraphicsObject's. if you want them to use signals and slots).
To view an area of the world, we use one or more QGraphicsViews.
In order to map between the different coordinate systems, Qt provides the useful mapTo and mapFrom functions.
Starting at the top, with a QGraphicsView, we can convert a coordinate and use QGraphicsView::mapToScene to get the coordinate in the scene's coordinate system. From this, if an item resides at that coordinate, we can get the coordinate relative to the item, using QGraphicsItem::mapFromScene.
So, with the three levels (view, scene and item) think about which system the coordinate is in and where you want to be dealing with it.
how get true position on graphic scene?
Hopefully you should now be thinking that the coordinate you have been provided in the MainWindow is in the view's coordinate system and you can map to the scene's coordinate system.
QPointF scenePoint = mapToScene(event->Pos());
However, this is overcomplicating things and you'll find it easier to work directly with the scene and the items it contains, by overloading the item's own mouseMove/Press/Release events, which provide QGraphicsScene coordinates.
I solved this problem with make my object, which inherit QGraphicView (MyQGraphicView) and then I declared function mousePressedEvent for this object. This help me.

MapView.zoomToBoundingBox() not zooming

I'm trying to zoom the map to a specific bounding box. I know I have to make the call AFTER the layout of the map is ready, so that is not the problem. The camera only gets centered on the bounding box, but it doesn't zoom as closely as possible, it just stays at whatever zoom level was set previously. What am I missing? How do I make it zoom as well?
The class MapController in the API allows to move and animate the map. Maybe you can look the zoomToSpanmethod.

Handing a touch on a rotated CCLayer

After I rotate a CCLayer, my boundingBox grows, instead of rotating. Perhaps to be expected.
My issue is, I'm relying on a user touch on this layer. When the layer is rotated as in the figure on the bottom of the attached image, the clickable area increases because I'm calling:
if(CGRectContainsPoint(clickableLayer.boundingBox, touchLocation))
This causes an issue because this bounding box after rotation is covering up other things that are also clickable.
How do I only perform an action if the actual layer is touched? I want something to happen when just the green box is clicked, not the boundingBox of the layer.
Thoughts?
You can use CGMutablePathRef to detect transparent part:
Refer my answer in this thread.
Information about How to create CGPath:Here
For more information, Click Here
This thread got me to my answer: http://www.cocos2d-iphone.org/forum/topic/272336

QGraphicsItem::setTransformOriginPoint bug when trying to scale image

I have created my own class by extending QGraphicsItem and I want to make it so that when someone does a wheel even while over this item, it scales.
This way, i can have multiple items in a scene, and scale each of them in and out as I please.
The problem is, I want the item to scale under the mouse cursor, much like google maps does. That is, a move forward will keep panning the image and scaling it, so taht the area in the vicinity around my mouse pointer is always in view.
void ImagePixmapItem::wheelEvent ( QGraphicsSceneWheelEvent * event ){
update();
qreal factor = 1.2;
if (event->delta() < 0)
factor = 1.0 / factor;
scale(factor, factor);
scaleFactor *=factor;
this->scene()->setSceneRect(0,0,this->boundingRect().width(), this->boundingRect().height());
}
This is the code I am using to do the scale. The problem is, it always seems to be scaling from the top left corner. Well, this is undesirable, beacuse if I scale in or out too much, eventually my area of interest around the mouse pointer has moved off the screen, and I have to either scroll manually or pan to the location, zoom, pan, etc, until i get to the desired level.
I tried to use the QGraphicsItem::setTransformOriginPoint, but no matter what values I put in there, it still seems to scale and such from the top left.
What can I add to that code I posted to get the desired effect?
I have achieved similar functionality in my Image-Manipulation application (scaling the view and having the area under my mouse stay in place and visible) but I scale the whole graphics-view not a specific item, so I don't know if this code can solve your problem.
Anyway, this is what I do in the constructor of my subclassed QGraphicsView (after I set the scene):
setTransformationAnchor(AnchorUnderMouse);
setResizeAnchor(AnchorViewCenter);
I also use the above functions, after each call to:
MyGraphicsView->setTransform(transform);
I'm not sure if this can help you, but I hope so.

Point-in-poly for QPainterPath with holes

I'm trying to use a QGraphicsPathItem to represent a polygon with a hole in it (think doughnut). I can get it to draw correctly, and the center is transparent. However, with item selection or movement turned on, I am able to interact with my object when clicking in the hole. I'd rather treat the hole as not part of the polygon.
I've done some testing, and it appears that QPainterPath::contains() will return true when I check a point within the hole. Will I need to subclass QGraphicsPathItem to implement a more specific contains() function, or is there something else I'm missing?
If you change the filling rule from default value Qt::OddEvenFill to Qt::WindingFill, can you still see the hole? I guess you'll not be able to see the hole. So the hole is actually not a "physical" hole in your path. If you are going to represent a polygon with a hole, you may need to subclass the QGraphicsPathItem, explicitly define outer most path and holes, and maintain the relationship among paths in different role.
You'll need to subclass QGraphicsPathItem and reimplement the shape method. Here's what I did to solve the similar problem with an unfilled versus filled rectangle. This particular case is subclassed from QGraphicsRectItem. This also has some adjustment to the path width to make it easier for the user to click on, essentially a buffer zone around the path.
In the case of a filled rectangle, the returned shape is simply a rectangle, but for an unfilled rectangle, it's a stroked path with an empty interior. Then the object only moves when the user drags the edge, but not the middle. Figuring out the QPainterPathStroker wasn't intuitive from the documentation, but it was actually pretty simple to use.
QPainterPath MyRectItem::shape (void) const
{
if (this->brush().style() != Qt::NoBrush)
{
return QGraphicsRectItem::shape();
}
// The rectangle is unfilled. Create a path outlining the rectangle.
QPainterPath path;
QRectF rect = this->rect();
path.moveTo (rect.topLeft());
path.lineTo (rect.topRight());
path.lineTo (rect.bottomRight());
path.lineTo (rect.bottomLeft());
path.lineTo (rect.topLeft());
QPainterPathStroker stroker;
if (this->pen().style() != Qt::NoPen)
{
// For easier selection, increase the pen width to provide a buffer zone
// around the line where the user can click and still select.
stroker.setWidth (this->pen().width() + 20);
stroker.setCapStyle (this->pen().capStyle());
stroker.setJoinStyle (this->pen().joinStyle());
}
return stroker.createStroke (path);
}