Using Math::Polygon to determine if point is inside a polygon. Not working - perl

I am trying to determine if a certain point is inside of a polygon. Trying to use Math::Polygon. I have the boundary of the polygon in a mySQL table as one record per point for the polygon:
example:
1,38.33208,-75.51919
2,38.33286,-75.52265
etc.
38,38.33208,-75.51919
No matter what I do, the routine will not show the point inside the polygon despite the fact that the point would be truly inside the polygon.
Here's the relevant code
use Math::Polygon;
my #poly = ();
$sqlc = "SELECT segment,lat,lon FROM boundary WHERE xxxxxxx ";
my $stcc = $dbh->prepare(qq{$sqlc});
$stcc->execute();
while(($seg,$slat,$slon) = $stcc->fetchrow_array())
{
$poly[$seg] = ([$slat,$slon]);
}
my $bound = Math::Polygon->new(points => #poly);
my #this_loc = ([$lat2,$lon2]);
if($bound->contains( $this_loc ))
{
# never reaches this point.
}
No matter what, I can't get the ->contains() routine to ever return true.
Any thoughts would be appreciated. Thanks.

There seems to be (at least) two errors:
my $bound = Math::Polygon->new(points => #poly);
the constructor takes a reference to an array, not an array. So it should be:
my $bound = Math::Polygon->new(points => \#poly);
Second, $bound->contains( ) takes a reference to a point array, so it should be:
if($bound->contains( \#this_loc )) { ... }

Related

Write scale/nested conversion with ASAMMDF

I am using this snippet in order to create a mf4 file with a value to text table, found in the examples from asammdf's github.
vals = 5
conversion = {
'val_{}'.format(i): i
for i in range(vals)
}
conversion.update(
{
'text_{}'.format(i): 'key_{}'.format(i).encode('ascii')
for i in range(vals)
}
)
sig = Signal(
np.arange(cycles, dtype=np.uint32) % 30,
t,
name='Channel_value_to_text',
conversion=conversion,
comment='Value to text channel',
)
sigs.append(sig)
mdf.append(sigs, comment='arrays', common_timebase=True)
Is there a way to create a table with ##TX blocks and also ##CC blocks?(in order to simulate a scale conversion)
Thank you!
If anyone needs it, I found the answer and it was simpler than expected.
Create another conversion (i.e conversion2) in the same manner as the first one, then reassign the value of one of the references to it.
conversionBlock = from_dict(conversion)
conversionBlock.referenced_blocks["text_4"] = from_dict(conversion2)

Get all outging connectors from a shape programmatically

I want to rename a connector after a shape has been dropped.
Lets say I have a shape1 and I dropped a shape2 connected with shape1.
I want the connector shape between shape1 and shape2 so that I can rename it.
I guess it depends on what stage you intercept the drop. If it's immediately, you might make some assumptions about how many connectors might be involved, but if if some time after the drop then you might want to determine how many connections are involved.
As an example, with the following shapes:
...you could approach this in a number of ways:
Use the GluedShapes method working back from ShapeTwo
Use the GluedShapes method including the 'from' shape
Iterate through the Connects collection of the Page
Iterate over the Connect objects in on your target shape (ShapeOne)
I would definitely try and use the GluedShapes method (which came into Visio in 2010) over the Connect objects, but I'm adding them here as they can be useful depending on what you're trying to achieve.
Here's an example using LINQPad:
void Main()
{
var vApp = MyExtensions.GetRunningVisio();
var vPag = vApp.ActivePage;
//For demo purposes I'm assuming the following shape IDs
//but in reality you'd get a reference by other methods
//such as Window.Selection, Page index or ID
var shpOne = vPag.Shapes.ItemFromID[1];
var shpTwo = vPag.Shapes.ItemFromID[2];
Array gluedIds;
Console.WriteLine("1) using GluedShapes with the 'to' shape only");
gluedIds = shpTwo.GluedShapes(Visio.VisGluedShapesFlags.visGluedShapesIncoming1D,"");
IterateByIds(vPag, gluedIds);
Console.WriteLine("\n2) using GluedShapes with the 'to' and 'from' shapes");
gluedIds = shpTwo.GluedShapes(Visio.VisGluedShapesFlags.visGluedShapesIncoming1D, "", shpOne);
IterateByIds(vPag, gluedIds);
Console.WriteLine("\n3) using the Connects collection on Page");
var pageConns = from c in vPag.Connects.Cast<Visio.Connect>()
where c.FromSheet.OneD != 0
group c by c.FromSheet into connectPair
where connectPair.Any(p => p.ToSheet.ID == shpOne.ID) && connectPair.Any(p => p.ToSheet.ID == shpTwo.ID)
select connectPair.Key.Text;
pageConns.Dump();
Console.WriteLine("\n4) using FromConnects and Linq to navigate from shpOne to shpTwo finding the connector in the middle");
var shpConns = from c in shpOne.FromConnects.Cast<Visio.Connect>()
where c.FromSheet.OneD != 0
let targetConnector = c.FromSheet
from c2 in targetConnector.Connects.Cast<Visio.Connect>()
where c2.ToSheet.Equals(shpTwo)
select targetConnector.Text;
shpConns.Dump();
}
private void IterateByIds(Visio.Page hostPage, Array shpIds)
{
if (shpIds.Length > 0)
{
for (int i = 0; i < shpIds.Length; i++)
{
//Report on the shape text (or change it as required)
Console.WriteLine(hostPage.Shapes.ItemFromID[(int)shpIds.GetValue(i)].Text);
}
}
}
Running the above will result in this output:
It's worth bearing in mind that the Connects code (3 and 4) makes the assumption that connector shape (1D) are being connected to the flowchart shapes (2D) and not the other way round (which is possible).
You can think of the connect objects as being analgous to connection points, so in the diagram, the three connector shapes generate six connect objects:
Anyway, hope that gets you unstuck.
UPDATE - Just to be clear (and to answer the original question properly), the code to get all outgoing connectors from ShapeOne would be:
Console.WriteLine("using GluedShapes to report outgoing connectors");
gluedIds = shpOne.GluedShapes(Visio.VisGluedShapesFlags.visGluedShapesOutgoing1D, "");
IterateByIds(vPag, gluedIds);

Zend_Db magic method specific cell selection

Currently I'm working on a couple of model related improvements and looking into a specific query I've wrote.
$queryGetPages = $this->fetchAll($this->select()
->where('page_active = ?', (int) $active)
->order('page_rank ASC'));
if($queryGetPages) {
$queryGetPages = $queryGetPages->toArray();
foreach($queryGetPages as $key => $value) {
$queryGetPagePrint = $this->find($value['pageid'])
->current()
->findModule_Model_ModulePagesPrintsViaModule_Model_ModulePagesFuses(
$this->select()
->from('module_pages_prints', array('print_title'))
->where('fuse_locale = ?', $this->_toolbox['editor']['translation']) )
}
}
The problem is in the magic method which is requesting data from a related table. I only need the 'title' cell per row, but for some reason it wont let me. Even with this query, it returns all cells from the row. I'm doing something wrong, but have no idea what!
If someone can point me to the right direction, I would be very thankfull.
Best regards !
The function that is implicitly called in your case is findManyToManyRowset() (code available in Zend/Db/Table/Row/Abstract.php, lines 1001-1108 (as of ZF 1.12.1). Have a look at lines 1070-1072:
$select->from(array('i' => $interName), array(), $interSchema)
->joinInner(array('m' => $matchName), $joinCond, Zend_Db_Select::SQL_WILDCARD, $matchSchema)
->setIntegrityCheck(false);
In short: the function that is called will overwrite your from() call and select all rows from the dependent table (module_pages_fuses). This is the way it's designed to work.
Instead, I would recommend writing the query you actually need the "dumb" way, e.g.
$queryGetPagePrint = $this->select()
->from(array('p' => 'module_pages_prints'), array('print_title'))
->join(array('f' => 'module_pages_fuses'),'p.pageid = f.pageid',array())
->where('f.fuse_locale = ?', $this->_toolbox['editor']['translation'])
->where('p.pageid = ?', $value['pageid']);

On Google Earth, can I vary the altitude on a lineString/LinearRing programmatically?

I am using the Google Earth plugin on an HTML page. In this context, say you have a line string or polygon like this
// Create the placemark
var lineStringPlacemark = ge.createPlacemark('');
// Create the LineString
var lineString = ge.createLineString('');
lineStringPlacemark.setGeometry(lineString);
// Add LineString points
lineString.getCoordinates().pushLatLngAlt(48.754, -121.835, 0);
lineString.getCoordinates().pushLatLngAlt(48.764, -121.828, 0);
// Add the feature to Earth
ge.getFeatures().appendChild(lineStringPlacemark);
I got the sample from https://developers.google.com/earth/documentation/geometries
Now, say you would like to vary the altitude (height) programmatically, after you append the lineString, how would you do it?
I saw you can retrieve the features through ge.getFeatures(). However, the returned object can not be inspected and I am struggling with the syntax to change the altitude.
I could remove the whole object and redraw it but that is hacky and the user can see the redraw. This is the code to remove
var features = ge.getFeatures();
while (features.getFirstChild())
features.removeChild(features.getFirstChild());
I got the code from https://developers.google.com/earth/documentation/containers
Does someone know the right syntax?
If you have a reference to the LineString (you can hold on to it, or walk the KML DOM and get it again), you can change the altitude of the entire LineString via
lineString.setAltitudeOffset(offsetFromCurrentAltitude);
If you want to change the altitude on a per coordinate basis, you can access them basically as you constructed it above. lineString.getCoordinates() returns the KmlCoordArray, and then you can read values from individual coordinates from there. One kind of awkward thing about KmlCoordArray is that it returns copies of its KmlCoord children, not its children directly. So you can do lineString.getCoordinates().get(0) and then read the lat/lng/alt values from the KmlCoord it returns, but if you set those values on that coordinate, it won't automatically be reflected in the LineString. Instead, you have to readd that KmlCoord to the KmlCoordArray. It's somewhat awkward, but useable.
So you might do something like this, if you're usually only altering one altitude at a time:
function setNewAltitude(lineString, coordIndex, altitude) {
var coords = lineString.getCoordinates();
if (coordIndex >= 0 && coordIndex < coords.getLength()) {
var coord = coords.get(coordIndex);
coord.setAltitude(altitude);
coords.set(coordIndex, coord);
}
}
Check out the KmlCoordArray reference page for its other methods to see if they would be more helpful for the exact use case you have in mind.
I found the answer. My insight was requesting the type as I navigated through the objects. See below
// read the number of features in GE
var length = ge.getFeatures().getChildNodes().getLength();
// get the first feature
var feature = ge.getFeatures().getFirstChild();
// for debugging get type - expecting KmlPlacemark
var featureType = feature.getType();
console.log(featureType);
// get KmlPlacemark geometry
var geometry = feature.getGeometry();
// for debugging get type - expecting KmlLineString
var geometryType = geometry.getType();
console.log(geometryType);
// get KmlLineString coordinates
var coordinates = geometry.getCoordinates();
// for debugging get type - expecting KmlCoordArray
var coordinatesType = coordinates.getType();
console.log(coordinatesType);
var altitude = Math.random()*10000;
var coordinatesLength = coordinates.getLength();
for(var i=0; i< coordinatesLength; i++){
var coordinate = coordinates.get(i);
console.log(coordinate.getType());
coordinate.setAltitude(altitude);
coordinates.set(i,coordinate)
}
for(var i=0; i< coordinatesLength; i++){
var coordinate = coordinates.get(i);
console.log(coordinate.getAltitude());
}

What is wrong with the below statement(C#3.0 / Lambda)

what is wrong in the below
Enumerable.Range(0, objEntityCode.Count - 1).Select(i =>
{
options.Attributes[i] = new EntityCodeKey
{
EntityCode = objEntityCode[i].EntityCodes
, OrganizationCode = Constants.ORGANIZATION_CODE };
})
.ToArray();
Throwing error The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
But this works
Enumerable.Range(0, objEntityCode.Count - 1).ToList().ForEach(i =>
{
options.Attributes[i] = new EntityCodeKey
{
EntityCode = objEntityCode[i].EntityCodes
, OrganizationCode = Constants.ORGANIZATION_CODE
};
}
);
Using C#3.0.
Purpose: I am learning LINQ / LAMBDA and trying to do the same program in different way.
Thanks.
As I stated in a comment - your lambda expression doesn't return anything. Therefore it can't be used in a projection. Select is meant to transform a sequence of items of one type into a sequence of items of another type. You're not doing any transforming in your lambda expression - you've just got an assignment.
Now you could do this:
Enumerable.Range(0, objEntityCode.Count - 1).Select(i =>
{
return options.Attributes[i] = new EntityCodeKey
{
EntityCode = objEntityCode[i].EntityCodes,
OrganizationCode = Constants.ORGANIZATION_CODE
};
})
.ToArray();
I wouldn't recommend it though. I appreciate you're currently learning about LINQ and lambda expressions, but it's worth learning when not to use them too - and this looks like a situation where you really, really shouldn't use them.
Look at what you have inside the Select and ForEach method calls:
options.Attributes[i] = new EntityCodeKey
{
EntityCode = objEntityCode[i].EntityCodes
, OrganizationCode = Constants.ORGANIZATION_CODE
};
This is essentially an Action<int> -- that is, code that does something but doesn't return something. This is why it makes sense within ForEach but not Select -- Select expects (in this case) a Func<int, T> -- code that returns something (of some type T). Since you are simply assigning Attributes[i] to a new EntityCodeKey, this code does not fall under the umbrella of what you would normally find within a Select call.
Note that technically, the above code actually would return something -- namely, the value stored in options.Attributes[i] -- if you removed the semicolon from the end. Why? Two reasons:
A single-line lambda expression (not terminating in a semi-colon) returns whatever it evaluates to. This is why something like person => person.Name can actually be interpreted as a Func<Person, string>.
An assignment operation evaluates to the assigned value. This is why you can write x = y = z -- because y = z actually evalutes to the newly assigned value of y.
So it's true: your code, sans semi-colon, would actually evaluate to options.Attributes[i]. But writing the code in this way would be, in my opinion anyway, pretty confusing.