How to map OSMSharp view point to Geo coordinate? - ios

I am using OSMSharp for an iOS project.
I'll like to be able to convert a given point in the view/map to GeoCoordinates (based on the current MapCenter, view size, zoom, etc).
I thought mapView.Map.Project.ToGeoCoordinates would do that, but the result is not correct. The inverse function (mapView.Map.Project.ToPixel) returns values in a coordinate system that doesn't correspond to the actual view (it returns value up to 10000 or so, and the size of my view is 1024x768).
So, how do I convert a given pixel coordinate in a OsmSharp.iOS.UI.MapView to its corresponding GeoCoordinate?.

Right now there's no method to get it. But it's easy to get
Add below method to MapView class in OsmSharp.iOS.UI project
public GeoCoordinate PointToCoordinate(int PointX, int PointY)
{
View2D view = _cacheRenderer.Create(this.Width, this.Height, this.Map,
(float)this.Map.Projection.ToZoomFactor(this.MapZoom), this.MapCenter, false, true);
// get scene coordinates.
double x, y;
var fromMatrix = view.CreateFromViewPort(this.Width, this.Height);
fromMatrix.Apply(PointX, PointY, out x, out y);
return this.Map.Projection.ToGeoCoordinates(x, y);
}
If you want the Point from Geocoordinate, add below method to the same class
public Point CoordinateToPoint(GeoCoordinate gc)
{
var gcPx = this.Map.Projection.ToPixel(gc);
View2D view = _cacheRenderer.Create(this.Width, this.Height, this.Map,
(float)this.Map.Projection.ToZoomFactor(this.MapZoom), this.MapCenter, false, true);
// get scene coordinates.
double x, y;
var fromMatrix = view.CreateFromViewPort(this.Width, this.Height);
fromMatrix.Remove(gcPx[0], gcPx[1], out x, out y);
return new Point((int)System.Math.Round(x, 0), (int)System.Math.Round(y, 0));
}
And below method to Matrix2D class in OsmSharp.UI.Renderer project
public void Remove(double x, double y, out double xNew, out double yNew)
{
xNew = (x * this.E11 - this.E02 * this.E11 + this.E01 * this.E12 - this.E01 * y) / (this.E00 * this.E11 - this.E01 * this.E10);
yNew = (y - this.E12 - this.E10 * xNew) / this.E11;
}

Related

Logic for jumping in webgl with physics enabled

Most important code just for example. Func UPDATE is called in every draw frame.
I want implement jumping virtualJumpActive == true logic.
I invert procedure for virtualJumpActive == true to make scene object and camera position set by cannonjs position but just in some short time.
My camera.posY follow fixed values for now.
I wanna only Y (for cannonjs Z / jumping ) to be navigated by physics and other XY
to be navigated by camera (WASD user control)...
It is little intricate situation, i have 3 factors
position of camera
position of player (hands)
position of player collision object
In normal regime player collision object follow camera and player.
In jump moment i wanna apply by vertical force and make camera follow collision object. Also i wanna that always Y component depens on physics data. In that way i will have jumping on top of other objects.
var playerUpdater = {
UPDATE: () => {
App.scene[objName].rotation.rotateY(
matrixEngine.Events.camera.yaw + 180)
var detPitch;
var limit = 2;
if(matrixEngine.Events.camera.pitch < limit &&
matrixEngine.Events.camera.pitch > -limit) {
detPitch = matrixEngine.Events.camera.pitch * 2;
} else if(matrixEngine.Events.camera.pitch > limit) {
detPitch = limit * 2;
} else if(matrixEngine.Events.camera.pitch < -(limit + 2)) {
detPitch = -(limit + 2) * 2;
}
if(matrixEngine.Events.camera.virtualJumpActive == true) {
// invert logic
// Scene object set
App.scene[objName].rotation.rotateX(-detPitch);
var detPitchPos = matrixEngine.Events.camera.pitch;
if(detPitchPos > 4) detPitchPos = 4;
App.scene[objName].position.setPosition(
App.scene.playerCollisonBox.physics.currentBody.position.x,
App.scene.playerCollisonBox.physics.currentBody.position.z,
App.scene.playerCollisonBox.physics.currentBody.position.y
)
// Cannonjs object set
// Switched Z - Y
matrixEngine.Events.camera.xPos = App.scene.playerCollisonBox.physics.currentBody.position.x;
matrixEngine.Events.camera.zPos = App.scene.playerCollisonBox.physics.currentBody.position.y;
matrixEngine.Events.camera.yPos = App.scene.playerCollisonBox.physics.currentBody.position.z;
// App.scene.playerCollisonBox.
// physics.currentBody.velocity.set(0, 0, 0);
App.scene.playerCollisonBox.
physics.currentBody.angularVelocity.set(0, 0, 0);
setTimeout(() => {
matrixEngine.Events.camera.virtualJumpActive = false;
matrixEngine.Events.camera.virtualJumpY = 2;
}, 350);
} else {
// Scene object set
App.scene[objName].rotation.rotateX(-detPitch);
var detPitchPos = matrixEngine.Events.camera.pitch;
if(detPitchPos > 4) detPitchPos = 4;
App.scene[objName].position.setPosition(
matrixEngine.Events.camera.xPos,
matrixEngine.Events.camera.yPos - 0.3 + detPitchPos / 50,
matrixEngine.Events.camera.zPos,
)
// Cannonjs object set
// Switched Z - Y
App.scene.playerCollisonBox.
physics.currentBody.position.set(
matrixEngine.Events.camera.xPos,
matrixEngine.Events.camera.zPos,
matrixEngine.Events.camera.yPos);
App.scene.playerCollisonBox.
physics.currentBody.velocity.set(0, 0, 0);
App.scene.playerCollisonBox.
physics.currentBody.angularVelocity.set(0, 0, 0);
}
}
};
.full {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
<object class="full" data="https://fps-matrix-engine.vercel.app"/>
Any suggestion ?
More data:
Stackoverflow Question ref code =>
https://codepen.io/zlatnaspirala/pen/eYKrmdM?editors=0010
Source code github
Last update
https://fps-matrix-engine.vercel.app

Flash Actionscript 2.0 localToGlobal co-ordinate issues

I don't know if anyone here is old enough to remember ActionScript 2.0 but unfortunately I find myself stuck with it as the game I am writing a mod for (Skyrim) still uses AS2 for UI.
I am using Greensock TweenLite/TimeLineLite for my animations/tweens, but I am having difficulty with what should be some simple co-ordinate calculations.
I am trying to animate icon A from it's starting position, scaling it up and moving in x and y, and finishing in exactly the same position and size as icon B.
Icon A and icon B are within different movieclips two levels up from a common parent clip, so I am trying to use localToGlobal to get stage x/y for each icon, and then moving in x/y by the differences between the two sets of stage co-ordinates.
So for example:
Icon A Global x = 95
Icon B Global x = 150
Difference = 55
Icon A Local x + 55 should put it in the same x position on stage as Icon B right? Well that's nowhere near the result I'm getting on screen, not even close.
To help visualise better this is how the widget looks in game:
Example screenshot
And this is how it looks in CS6:
Flash workspace
So for example I am attempting to move/scale leftPreselectIcon (Dragonbone War Axe in the example screenshot) into exactly the position of leftIcon (Staff of Firebolts).
Here are the relevant functions:
public function prepareForPreselectAnimation(): Void
{
//This function checks if the preselect icons are to the left or right of their main icon and sets the animate out direction to the opposite side. It also stores current main icon x/y as the target values for the preselect icons to animate to. Finally it gets and stores all necessary current scale and alpha values to ensure everything returns to the exact state it was in prior to starting the animation
var leftIconLTG:Object = {x:(leftIcon._height * 0.5), y:(leftIcon._width * 0.5)};
var leftPreselectIconLTG:Object = {x:(leftPreselectIcon._height * 0.5), y:(leftPreselectIcon._width * 0.5)};
var rightIconLTG:Object = {x:(rightIcon._height * 0.5), y:(rightIcon._width * 0.5)};
var rightPreselectIconLTG:Object = {x:(rightPreselectIcon._height * 0.5), y:(rightPreselectIcon._width * 0.5)};
var shoutIconLTG:Object = {x:(shoutIcon._height * 0.5), y:(shoutIcon._width * 0.5)};
var shoutPreselectIconLTG:Object = {x:(shoutPreselectIcon._height * 0.5), y:(shoutPreselectIcon._width * 0.5)};
leftIcon.localToGlobal(leftIconLTG);
leftPreselectIcon.localToGlobal(leftPreselectIconLTG);
rightIcon.localToGlobal(rightIconLTG);
rightPreselectIcon.localToGlobal(rightPreselectIconLTG);
shoutIcon.localToGlobal(shoutIconLTG);
shoutPreselectIcon.localToGlobal(shoutPreselectIconLTG);
skyui.util.Debug.log("leftIconLTG - x: " + leftIconLTG.x + ", y: " + leftIconLTG.y)
skyui.util.Debug.log("leftPreselectIconLTG - x: " + leftPreselectIconLTG.x + ", y: " + leftPreselectIconLTG.y)
if (leftIconLTG.x > leftPreselectIconLTG.x){
leftTargetX = (leftIcon_mc._width) //If preselect icon is to the left of the main widget animate main widget out to right
//leftPTargetX = (leftIconLTG.x - leftPreselectIconLTG.x) + (leftIcon._width / 2)
} else {
leftTargetX = -(leftIcon_mc._width) //If preselect icon is to the right of the main widget animate main widget out to left
//leftPTargetX = (leftIconLTG.x - leftPreselectIconLTG.x) - (leftIcon._width)
}
leftPTargetX = (leftIconLTG.x - leftPreselectIconLTG.x)
skyui.util.Debug.log("leftTargetX: " + leftTargetX + ", leftPTargetX: " + leftPTargetX)
if (rightIconLTG.x > rightPreselectIconLTG.x){
rightTargetX = (rightIcon_mc._width)
//rightPTargetX = (rightIconLTG.x - rightPreselectIconLTG.x) + (rightIcon._width / 2)
} else {
rightTargetX = -(rightIcon_mc._width)
//rightPTargetX = (rightIconLTG.x - rightPreselectIconLTG.x) - (rightIcon._width)
}
rightPTargetX = (rightIconLTG.x - rightPreselectIconLTG.x)
if (shoutIconLTG.x > shoutPreselectIconLTG.x){
shoutTargetX = (shoutIcon_mc._width)
//shoutPTargetX = (shoutIconLTG.x - shoutPreselectIconLTG.x) + (shoutIcon._width / 2)
} else {
shoutTargetX = -(shoutIcon_mc._width)
//shoutPTargetX = (shoutIconLTG.x - shoutPreselectIconLTG.x) - (shoutIcon._width)
}
shoutPTargetX = (shoutIconLTG.x - shoutPreselectIconLTG.x)
leftPTargetY = leftIconLTG.y - leftPreselectIconLTG.y;
skyui.util.Debug.log("leftPTargetY: " + leftPTargetY)
rightPTargetY = rightIconLTG.y - rightPreselectIconLTG.y;
shoutPTargetY = shoutIconLTG.y - shoutPreselectIconLTG.y;
//Store current alpha and scale values ready to reapply
leftIconAlpha = leftIcon_mc._alpha;
leftTargetScale = ((leftIcon_mc._xscale / leftPreselectIcon_mc._xscale) * 100);
//leftPTargetX = ((leftIconLTG.x - leftPreselectIconLTG.x) * (leftIcon_mc._xscale / leftPreselectIcon_mc._xscale));
leftPIconAlpha = leftPreselectIcon_mc._alpha;
leftPIconScale = leftPreselectIcon._xscale;
rightIconAlpha = rightIcon_mc._alpha;
rightTargetScale = ((rightIcon_mc._xscale / rightPreselectIcon_mc._xscale) * 100);
rightPIconAlpha = rightPreselectIcon_mc._alpha;
rightPIconScale = rightPreselectIcon._xscale;
shoutIconAlpha = shoutIcon_mc._alpha;
shoutTargetScale = ((shoutIcon_mc._xscale / shoutPreselectIcon_mc._xscale) * 100);
shoutPIconAlpha = shoutPreselectIcon_mc._alpha;
shoutPIconScale = shoutPreselectIcon._xscale;
leftNameAlpha = leftName_mc._alpha;
leftPNameAlpha = leftPreselectName_mc._alpha;
rightNameAlpha = rightName_mc._alpha;
rightPNameAlpha = rightPreselectName_mc._alpha;
shoutNameAlpha = shoutName_mc._alpha;
shoutPNameAlpha = shoutPreselectName_mc._alpha;
skse.SendModEvent("iEquip_ReadyForPreselectAnimation", null);
}
public function equipPreselectedItem(iSlot: Number, currIcon: String, newIcon: String, newName: String, currPIcon: String, newPIcon: String, newPName: String): Void
{
var iconClip: MovieClip;
var iconClip_mc: MovieClip;
var currIcon: String;
var pIconClip: MovieClip;
var pIconClip_mc: MovieClip;
var currPIcon: String;
var itemName_mc: MovieClip;
var preselectName_mc: MovieClip;
var targetX: Number;
var pTargetX: Number;
var pTargetY: Number;
var pIconAlpha: Number;
var pIconScale: Number;
var pIconTargetScale: Number
var iconAlpha: Number;
var itemNameAlpha: Number;
var preselectNameAlpha: Number;
switch(iSlot) {
case 0:
iconClip = leftIcon;
iconClip_mc = leftIcon_mc;
pIconClip = leftPreselectIcon;
pIconClip_mc = leftPreselectIcon_mc;
itemName_mc = leftName_mc;
preselectName_mc = leftPreselectName_mc;
targetX = leftTargetX;
pTargetX = leftPTargetX;
pTargetY = leftPTargetY;
pIconAlpha = leftPIconAlpha;
pIconScale = leftPIconScale;
iconAlpha = leftIconAlpha;
pIconTargetScale = leftTargetScale;
itemNameAlpha = leftNameAlpha;
preselectNameAlpha = leftPNameAlpha;
break
case 1:
iconClip = rightIcon;
iconClip_mc = rightIcon_mc;
pIconClip = rightPreselectIcon;
pIconClip_mc = rightPreselectIcon_mc;
itemName_mc = rightName_mc;
preselectName_mc = rightPreselectName_mc;
targetX = rightTargetX;
pTargetX = rightPTargetX;
pTargetY = rightPTargetY;
pIconAlpha = rightPIconAlpha;
pIconScale = rightPIconScale;
iconAlpha = rightIconAlpha;
pIconTargetScale = rightTargetScale;
itemNameAlpha = rightNameAlpha;
preselectNameAlpha = rightPNameAlpha;
break
case 2:
iconClip = shoutIcon;
iconClip_mc = shoutIcon_mc;
pIconClip = shoutPreselectIcon;
pIconClip_mc = shoutPreselectIcon_mc;
itemName_mc = shoutName_mc;
preselectName_mc = shoutPreselectName_mc;
targetX = shoutTargetX;
pTargetX = shoutPTargetX;
pTargetY = shoutPTargetY;
pIconAlpha = shoutPIconAlpha;
pIconScale = shoutPIconScale;
iconAlpha = shoutIconAlpha;
pIconTargetScale = shoutTargetScale;
itemNameAlpha = shoutNameAlpha;
preselectNameAlpha = shoutPNameAlpha;
break
}
var tempIcon: MovieClip = iconClip.duplicateMovieClip("tempIcon", this.getNextHighestDepth());
tempIcon.gotoAndStop(currIcon);
iconClip._alpha = 0;
iconClip.gotoAndStop(newIcon);
var tempPIcon: MovieClip = pIconClip.duplicateMovieClip("tempPIcon", this.getNextHighestDepth());
//var iconLTG: Object = {x:(iconClip._width * 0.5), y:(iconClip._height * 0.5)}
//iconClip.localToGlobal(iconLTG);
//var tempPIconLTG: Object = {x:(tempPIcon._width * 0.5), y:(tempPIcon._height * 0.5)}
//tempPIcon.localToGlobal(tempPIconLTG);
//pTargetX = ((iconLTG.x - tempPIconLTG.x) * (iconClip_mc._xscale / pIconClip_mc._xscale));
//skyui.util.Debug.log("iconLTG.x: " + iconLTG.x + ", iconLTG.y: " + iconLTG.y + "tempPIconLTG.x: " + tempPIconLTG.x + ", tempPIconLTG.y: " + tempPIconLTG.y + ", pTargetX: " + pTargetX)
tempPIcon._xscale = pIconClip_mc._xscale;
tempPIcon._yscale = pIconClip_mc._yscale;
tempPIcon.gotoAndStop(currPIcon);
pIconClip._alpha = 0;
pIconClip._xscale = 25;
pIconClip._yscale = 25;
pIconClip.gotoAndStop(newPIcon);
var tl = new TimelineLite({paused:true, autoRemoveChildren:true, onComplete:equipPreselectedItemComplete});
tl.to(itemName_mc, 0.3, {_alpha:0, ease:Quad.easeOut}, 0)
.to(preselectName_mc, 0.3, {_alpha:0, ease:Quad.easeOut}, 0)
.call(updateNamesForEquipPreselect, [iSlot, newName, newPName, this])
.to(tempIcon, 0.6, {_x:targetX, _y:((tempIcon._height) / 2), _rotation:"+=90", _alpha:0, _xscale:25, _yscale:25, ease:Quad.easeOut}, 0);
.to(tempPIcon, 0.6, {_x:pTargetX, _y:pTargetY, _alpha:iconAlpha, _xscale:pIconTargetScale, _yscale:pIconTargetScale, ease:Quad.easeOut}, 0)
.to(iconClip, 0, {_alpha:iconAlpha, ease:Linear.easeNone})
.to(tempPIcon, 0, {_alpha:0, ease:Linear.easeNone})
.to(pIconClip, 0.4, {_alpha:pIconAlpha, _xscale:pIconScale, _yscale:pIconScale, ease:Elastic.easeOut}, 0.5)
.to(itemName_mc, 0.3, {_alpha:itemNameAlpha, ease:Quad.easeOut}, 0.6)
.to(preselectName_mc, 0.3, {_alpha:preselectNameAlpha, ease:Quad.easeOut}, 0.6)
tl.play();
}
I have also uploaded it to Pastebin HERE
The straightforward Icon A X value + Global X value difference which should work results in this:
Screenshot 2
And the issue is worse the greater the distance between the two icons is to start with. If I edit the starting position of Icon A to be much further away this is the result:
Screenshot 3
From those two examples the logged values and calculations are:
[20:12:47.970] leftIconLTG - x: 149.49916992187, y: 581.28598632812
[20:12:47.970] leftPreselectIconLTG - x: 94.587438964844, y: 577.68461914063
[20:12:47.970] leftTargetX: 39.15, leftPTargetX: 54.911730957031
[20:12:47.970] leftPTargetY: 3.6013671874999
[20:13:18.510] leftIconLTG - x: 149.49916992187, y: 581.28598632812
[20:13:18.510] leftPreselectIconLTG - x: 594.56030273438, y: 577.68461914063
[20:13:18.510] leftTargetX: -58.55, leftPTargetX: -445.0611328125
[20:13:18.510] leftPTargetY: 3.6013671874999
So as you can see the target leftIcon global (LTG) x is 149.5, and in the first screenshot the leftPreselectIcon starts at a global x of 94.6. leftPTargetX contains the difference calculated correctly at 54.9. So moving leftPreselectIcon from it's local starting x of 0 to 54.9 should in theory move it into the correct position.
So what am I doing wrong here? As you can see from the commented out code I have made several other attempts including adding half/full icon widths to the calculation, and even testing whether the difference in scale has anything to do with it by multiplying the global x difference value by the scale factor going from icon A scale to icon B scale using the on screen heights for the calculation. But none of them get me close.
Solved
The solution was to create 'store' objects for each set of icons, and then call localToGlobal on the target icon, then globalToLocal on the icon to be moved, both calls on the same object:
var leftPIconTarget:Object = {x:0, y:0};
leftIcon.localToGlobal(leftPIconTarget);
leftPreselectIcon.globalToLocal(leftPIconTarget);
leftPIconTarget now contains the target x and y co-ordinates for the tween on leftPreselectIcon, and continues to work no matter where on the screen I move the starting positions to. The only wierdness is that I have to make the right x negative or it goes in the wrong direction, which makes no sense at all, because if I move the left icon way over to the right so it has to animate right to left I don't have to make it negative. Go figure! Anyway, it works, and that's all I'm bothered about!

Highcharts: plotbands in gauge charts

I'm using plotbands in a gauge chart to represent angle ranges. But I'm facing a problem with the plotband angles when the "from" value is higher than the "to" value.
JSFiddle
As you can see, the plotband is set as from: 270, to: 45 but it really is rendered as if it was set as from: 45, to: 270. That renders exactly the oposite angle range that I need.
The only way that I can find to do that is setting two plotbands, one from 270 to 360 and another one from 0 to 45, but that seems very unconvenient.
Is there any easy way to achieve what I'm trying to do?
As I have mentioned in my comment, I think that you should be able to override getPlotBand method in your code for enabling plotBands with bigger from value than to value:
(function(H) {
H.wrap(H.Axis.prototype, 'init', function(proceed, chart, userOptions) {
this.getPlotBandPath = function(from, to, options) {
var center = this.center,
startAngleRad = this.startAngleRad,
pick = H.pick,
map = H.map,
pInt = H.pInt,
fullRadius = center[2] / 2,
radii = [
pick(options.outerRadius, '100%'),
options.innerRadius,
pick(options.thickness, 10)
],
offset = Math.min(this.offset, 0),
percentRegex = /%$/,
start,
end,
open,
isCircular = this.isCircular, // X axis in a polar chart
ret;
// Polygonal plot bands
if (this.options.gridLineInterpolation === 'polygon') {
ret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true));
// Circular grid bands
} else {
// Keep within bounds
from = Math.max(from, this.min);
to = Math.min(to, this.max);
// Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from
if (!isCircular) {
radii[0] = this.translate(from);
radii[1] = this.translate(to);
}
// Convert percentages to pixel values
radii = map(radii, function(radius) {
if (percentRegex.test(radius)) {
radius = (pInt(radius, 10) * fullRadius) / 100;
}
return radius;
});
// Handle full circle
if (options.shape === 'circle' || !isCircular) {
start = -Math.PI / 2;
end = Math.PI * 1.5;
open = true;
} else {
start = startAngleRad + this.translate(from);
end = startAngleRad + this.translate(to);
}
radii[0] -= offset; // #5283
radii[2] -= offset; // #5283
ret = this.chart.renderer.symbols.arc(
this.left + center[0],
this.top + center[1],
radii[0],
radii[0], {
start: start, // Math is for reversed yAxis (#3606)
end: end,
innerR: pick(radii[1], radii[0] - radii[2]),
open: open
}
);
}
return ret;
}
proceed.call(this, chart, userOptions);
});
}(Highcharts))
Live example:
http://jsfiddle.net/2Ljk7usL/9/

Local integer values changing randomly inside while loop

I have a function which does some array manipulation on an NSMutableArray. Somehow after a couple of loops of the while function the values inside 2 local variables are total garbage. They are not being assigned or manipulated anywhere. Here's how:
Here's the function:
-(void) normalize_path:(NSMutableArray *)path tool:(Tool)tool
{
NSUInteger last_accepted_point_index = 0;
NSUInteger current_point_index = 1;
while(current_point_index < [path count]){
VPoint * p1, * p2;
[[path objectAtIndex:last_accepted_point_index] getValue:&p1];
[[path objectAtIndex:current_point_index] getValue:&p2];
//float distance = [self distance_between:p1 and:p2];
// if(distance < MIN_POINT_DISTANCE){
// [path removeObjectAtIndex:current_point_index];
// }else{
// float opacity = tool.max_opacity - distance * tool.opacity_sensitivity;
// opacity = opacity <= tool.min_opacity ? tool.min_opacity : opacity;
// p2->opacity = opacity;
// float thickness = tool.max_thickness - distance * tool.thickness_sensitivity;
// thickness = thickness <= tool.min_thickness ? tool.min_thickness : thickness;
// p2->thickness = thickness;
// last_accepted_point_index = current_point_index;
// //current_point_index++;
// }
}
}
And it's called only in one place like so:
//...
[self normalize_path:opath tool:pen];
//...
Every run creates different values. I am confounded! What is going on here?
I think that this may be a memory issue which you can fix by removing the & from in front of p1 and p2 in the getValue: call. It's difficult to be totally sure as you haven't said what VPoint is, but normally this code would look like this:
VPoint p1, p2;
[[path objectAtIndex:last_accepted_point_index] getValue:&p1];
[[path objectAtIndex:current_point_index] getValue:&p2];
This would then set p1 and p2 to the actual values. Your distance between function would then not take references but the actual values of p1 and p2 (if you want to pass references as you are doing now, you'd put & in front of p1 and p2 in the distance callBetween method call.

Selecting a Region OpenCV

I am new to OpenCV and I want to select a particular region in the video/image for detection. In my case I want to detect cars that are only in the road not in the parking lot.
Well, selecting cars requires use of training data. But to select an ROI (region of interest) is fairly simple:
Consider img = cv2.imread(image)
In that case, somewhere in your code, you can specify a region this way:
sub_image = img[y:y+h, x:x+w]
That will get the ROI once you specify the values, of course, not using 'x' or 'y', where h is the height and w is the width. Remember that images are just 2D matrices.
Use CascadeClassifier() to select the car(s) from the image(s). Documentation is found here. OpenCV comes packed with training data you can use to make classifications in the form of XML files.
If you want to manually select a region of interest (ROI) to do some processing on it, then you may trying using mouse click event to select start and stop points of your ROI.
Once you have start and stop point you can use it to retrieve image from selected region.
The can be done on image or capture video frame.
bool roi_captured = false;
Point pt1, pt2;
Mat cap_img;
//Callback for mousclick event, the x-y coordinate of mouse button-up and button-down
//are stored in two points pt1, pt2.
void mouse_click(int event, int x, int y, int flags, void *param)
{
switch(event)
{
case CV_EVENT_LBUTTONDOWN:
{
std::cout<<"Mouse Pressed"<<std::endl;
if(!roi_capture)
{
pt1.x = x;
pt1.y = y;
}
else
{
std::cout<<"ROI Already Acquired"<<std::endl;
}
break;
}
case CV_EVENT_LBUTTONUP:
{
if(!got_roi)
{
Mat cl;
std::cout<<"Mouse LBUTTON Released"<<std::endl;
pt2.x = x;
pt2.y = y;
cl = cap_img.clone();
Mat roi(cl, Rect(pt1, pt2));
Mat prev_imgT = roi.clone();
std::cout<<"PT1"<<pt1.x<<", "<<pt1.y<<std::endl;
std::cout<<"PT2"<<pt2.x<<","<<pt2.y<<std::endl;
imshow("Clone",cl);
got_roi = true;
}
else
{
std::cout<<"ROI Already Acquired"<<std::endl;
}
break;
}
}
}
//In main open video and wait for roi event to complete by the use.
// You capture roi in pt1 and pt2 you can use the same coordinates for processing // //subsequent frame
int main(int argc, char *argv[])
{
int frame_num = 0;
int non_decode_frame =0;
int count = 1, idx =0;
int frame_pos =0;
std::cout<<"Video File "<<argv[1]<<std::endl;
cv::VideoCapture input_video(argv[1]);
namedWindow("My_Win",1);
cvSetMouseCallback("My_Win", mouse_click, 0);
sleep(1);
while(input_video.grab())
{
cap_img.release();
if(input_video.retrieve(cap_img))
{
imshow("My_Win", cap_img);
if(!got_roi)
{
//Wait here till user select the desire ROI
waitKey(0);
}
else
{
std::cout<<"Got ROI disp prev and curr image"<<std::endl;
std::cout<<"PT1"<<pt1.x<<" "<<pt1.y<<std::endl;
std::cout<<"PT2"<<pt2.x<<" "<<pt2.y<<std::endl;
Mat curr_img_t1;
Mat roi2(cap_img,Rect(pt1, pt2));
Mat curr_imgT = roi2.clone();
cvtColor(curr_imgT, curr_img_t1, CV_RGB2GRAY);
imshow("curr_img", curr_img);
// Do remaining processing here on capture roi for every frame
waitKey(1);
}
}
}
}
You didn't tag in what programming language you are writing with. Anyway, I answer you in python. (You can easily convert it to C++ if you want)
def mouse_drawing(event, x, y, flags, params):
if event == cv2.EVENT_LBUTTONDOWN:
car = img[y: y + carheight, x: x + carwidth]
cv2.imwrite("car", car)
cv2.namedWindow("my_img")
cv2.setMouseCallback("my_img", mouse_drawing)
while True:
cv2.imshow("my_img", img)
key = cv2.waitKey(1)
if key == 27:
break
As in other answers was told, if you want to find cars automatically, that would be another problem and has to do with training data and other things.

Resources