Get index of an SKPoint in an SKPath - xamarin

I'm not seeing an IndexOf or FindIndex method for SKPath.Points. I need to be able to get neighbouring points on both sides of a specified point. Path.Iterator only has .Next, so I am looking for using the index of the SKPoint instead.
With IndexOf or FindIndex seemingly missing, I am thinking of inheriting and maintaining a 2nd dataset in the background for getting the index.
Am I missing something obvious? How are others getting the index, so far?

This post helped. Calling IndexOf directly on Array works. Just need to make sure your SKPoint X and Y are unique from other SKPoints stored in the SKPath.Points. It is doing the check based on the SKPoint's position, so if you have multiple SKPoints at (0, 0), for example, it will return the first one at that position.
Luckily, I should never be in the situation for my use case.

Related

Gremlin Sack Sum Once Per Distinct Value

Referencing this example from Practical Gremlin and this stack overflow post:
Gremlin Post Filter Path
g.withSack(0).V().
has('code','AUS').
repeat(out().simplePath().has('country',within('US','UK')).
choose(has('code','MAN'),sack(sum).by(constant(1)))).
until(has('code','EDI')).
where(sack().is(1)).
path().by('code').
limit(10)
Is it possible to perform a sack sum in such a way as to only sum the first time a property is found. For instance, instead of the 'code' property inside of the choose() which will only sum once per 'code' encountered thanks to the simplePath(), what if there was another property called 'airport_color'. As we perform the traversal, I would only want the sack sum to increment the first time it encountered 'blue' or 'white' as an example, even though multiple airports could have the same color as we go through the traversal. This would help me in the where() clause because, if I had a couple of colors I was interested in looking for as an example (maybe blue and white), I could set the where() clause to be equal to two and know that two wasn't arrived at just because I passed through blue twice but because blue and white was encountred.
I tried using aggregation to make the sack sum increment only on the first encounter but couldn't get it to work, something like this:
g.withSack(0).V().
has('code','AUS').
repeat(out().simplePath().has('country',within('US','UK')).
choose(has('airport_color','blue').has('airport_color', without('airport_color_agg')),sack(sum).by(constant(1))).
aggregate('airport_color_agg').by('airport_color')).
until(has('code','EDI')).
where(sack().is(1)).
path().by('code').
limit(10)
There could be multiple colors in the choose() via or() but I limited it to just one to keep the example more straightforward.
Thanks for your help!
Using the sample graph below:
g.addV('A').property(id,'a1').property('color','red').as('a1').
addV('A').property(id,'a2').property('color','blue').as('a2').
addV('A').property(id,'a3').property('color','red').as('a3').
addV('A').property(id,'a4').property('color','yellow').as('a4').
addV('A').property(id,'a5').property('color','green').as('a5').
addV('A').property(id,'a6').property('color','blue').as('a6').
addE('R').from('a1').to('a2').
addE('R').from('a2').to('a3').
addE('R').from('a3').to('a4').
addE('R').from('a4').to('a5').
addE('R').from('a5').to('a6')
we can inspect the path through the graph as follows:
g.V('a1').
repeat(out()).
until(not(out())).
path().
by('color')
which shows us the colors found
path[red, blue, red, yellow, green, blue]
the next thing we need to do is to remove the duplicates and filter out the colors not in our want list.
g.withSideEffect('want',['red','green']).
V('a1').
repeat(out()).
until(not(out())).
path().
by('color').
dedup(local).
unfold().
where(within('want'))
which gives us:
red
green
finally, we just need to count them:
g.withSideEffect('want',['red','green']).
V('a1').
repeat(out()).
until(not(out())).
path().
by('color').
dedup(local).
unfold().
where(within('want')).
count()
Which, as expected, gives us:
2
UPDATED 2022-09-01 To reflect discussion in comments.
To change the query so that only paths that visit each of the required colors at least once are returned, the previous steps leading up to the count need to be turned into a filter.
g.withSideEffect('want',['red','green']).
V('a1').
repeat(out()).
until(not(out())).
filter(
path().
by('color').
dedup(local).
unfold().
where(within('want')).
count().is(2)).
path()
which for our sample graph returns:
1 path[v[a1], v[a2], v[a3], v[a4], v[a5], v[a6]]
The query as written gets the job done and hopefully is not too hard to follow. There are some things we could change/improve.
Pass in the count for the is step as another parameter like the want list.
Rather than pass in a parameter, use the size of the want list instead. This makes the query a little more complex.
Use a sack as the query proceeds to collect the colors seen. The query gets more complex in that case as, while you can maintain a list in a sack, updating it requires a few extra steps.
Here is the query rewritten to use a sack. This assumes the start node has a color that should be included. If that is not the case, the first sack(assign) can be removed and a withSack([]) added after the withSideEffect.
g.withSideEffect('want',['red','green']).
V('a1').
sack(assign).by(values('color').fold()).
repeat(out().sack(assign).by(union(sack().unfold(),values('color')).fold())).
until(not(out())).
filter(
sack().
unfold().
dedup().
where(within('want')).
count().is(2)).
path()

Mapbox - setFilter expression for 'Contains' name within array of possible values

I'm trying filter my Mapbox layer (mapboxgl) to return just places that start with say 'North', 'South, 'East' or 'West'.
My places are in geojson data as a property.
I'm using map.setFilter with an expression to filter the geojson.
Example:
map.setFilter('markers', ["all",filter1,filter2]);
Where filter2 is a simple check on if the place is 'open' or 'closed' and filter1 is my main filter expression explained below.
The main issue is that the name of the place needs to START with one of these values.
So far I can do this IF the strings to check are all the same length by grabbing the length of the strings and then filtering by that substring of the name.
But this doesn't work (obviously) when I have words that are not the same length.
This is pretty simple in most other languages, but my brain cant figure out this in mapbox's expression filters for some reason!
Here's what I have so far (please excuse the poor code quality here, I'm not a professional coder!!):
//the array data to check for a match
filterArray = ['North','South','East','West'];
//checks first values length - not ideal!
var lengthToCheck = filterArray[0].length;
//apply it to the filter to only return ones starting with X
filter1 = ['in', ['slice',['to-string', ['get', 'name']],0,lengthToCheck], ['literal', filterArray]];
I have to slice the name of the place as it might be for example 'Northampton', which wont be found within the array value[0] being 'North'.
This is equally as bad code for the 'East' values as the name slice is going to be 5 characters, so it will be trying something like 'Eastb' (Eastbourne) within the array value 'East' which just wont work.
It would be good if I could some how flip this round so the filter can check the values in the array within the Name, but I can't figure this out!
Is there a way to do that or is there a magic expression feature I'm missing that would solve this problem?
I'm also going to have the same problem with a 'Contains' type check of an array of values too, but I'll cross that bridge once I figure this part out!
Any help appreciated (before I go putting in some convoluted workaround!).

Why in THREE.js the arithmetic expression in Object3D.translateX isn't evaluated as expected or Vector.copy doesn't work correctly in animate loop?

I'm trying to move an object called "car" via the dat.gui. If the user changes the x value using the dat.gui slider, the car should move along the x-axis of its local coordinate system.
here I have copied the part of the code that is causing me problems:
var m = new THREE.Vector3;
m.copy(car.position);
if (changed.key=='X') car.translateX(changed.value-car.worldToLocal(m).x);
My problem is that the expression in car.translateX always evaluates to the value that is in changed.value. The part after the minus has no effect at all or maybe is permanently 0. I have printed the values ​with console.log and the values ​​of car.position.x and m change in each step, but the subtraction still delivers in every step only the result that is already in changed.value anyway. Can someone help me and tell me why this happens?
Unfortunately, I am absolutely stuck.
car.worldToLocal(m)
I'm afraid this piece of code makes no sense since car.position (and thus m) already represents the car's position in local space.
Instead of using translateX() you achieve the same result by modifying car.position directly:
car.position.x = changed.value;

Spring Data JPA fetching list always returns at least a single result

I've noticed a slight problem with how my API is working where I'm using Spring Data JPA.
My query looks something along the lines of:
#Query("SELECT p.id AS id, COUNT(l) AS likes FROM Post p LEFT JOIN Like l ON l.post = p WHERE p.location.id = ?1")
My actual query is bigger, this this contains everything necessary to explain what the issue is. This query will return a list, but assume the location does not exist, it should return null or an empty list, correct? Oh, how wrong you are, my sweet summer child!
This query will instead always return a list of at least one element, regardless of whether or not there are any posts linked to said location.
[{"id": null, "likes": 0}]
That is what the result looks like when serialized to JSON. I am not quite sure what to do about this little predicament, as I obviously don't want to return a list with faulty data, but needing to use processing to filter out duds also seems dumb and unnecessary.
Is there any way to prevent this that I've yet to find? If it is of any relevance, I am using projections currently for my responses.
What I've tried so far:
Adding a not null condition for fields. Does not work, ignored by COUNT.
Adding constraints to all fields #NotNull. Does not work, will still become null.
For what it's worth, I've tried different kinds of joins, though anything but LEFT JOIN doesn't make much sense.
I haven't been able to find any other case which resembles this either, although it most likely exists, but is drowned out by everything else. I'm not quite sure what can be done in this regard, so I'm curious if it's just a quirk with the framework, or if there is an actual solution.
It might be possible to solve through native queries, but I would prefer not to use them.
I'm no SQL expert but I believe that a left join will give you this result if the ID does not exist.
Have you run the query in your DB? Doesn't it give you one row in your result set for IDs that do not exist?
I believe this is intended to say there is a 0 match.
You might want to validate your query before running it. Meaning checking that the location exists first.
As the issue is inherently due to a COUNT and CASE keyword in my real query, resulting in there always being at least one row, and I can't find any method of doing this automatically, the solution I've used is the following:
List<Item> items = repository.customQuery(id);
if (0 < items.size() && null == items.get(0).getId()) {
items.remove(0);
}
The first condition is arbitrary as I know there is always at least one entry, but is done just as a safety measure. A try-catch block would do the trick as well. In the case where you use a primitive int instead of Integer, you'd need to initialize the value in the constructor to something which would normally never be present in the database, such as -1.
If anyone knows of a better method, I'd love to know about it.

Google Sheets/Excel: Checking if a time falls within a range

I'm trying to find a way to see if I can find a way to determine if a time that I stipulate falls between two other times. For example:
Start End
11:33:48 11:53:48
12:20:22 12:38:21
12:39:27 13:00:09
14:16:23 14:20:49
14:20:54 14:22:56
Then, I want to check if a cell (here the value of 12:50 in cell E30) falls between ANY two values in a range in THE SAME ROW. For me, I can get the obvious way to check for this in one row, and this simple version totally works:
=If(AND(E30>A4,E30<B4), "TRUE", "FALSE")
However, I want to check if that number falls within ANY of the values within the ROWS above cells in a range, and I can't get that to work. For example, I tried this and it didn't work:
=If(AND(E30>A:A,E30<B:B), "TRUE", "FALSE")
I also tried a simple countif variation but that didn't do it either:
=COUNTIFS(A:A,">"&E30,B:B,"<"&E30)
Any advice on how to adjust one of these formulas to get it to work?
Try switching the angle brackets around:
=COUNTIFS(A:A,"<"&E30,B:B,">"&E30)
I think this should work for the above data set -
=IF((FILTER(A2:B6, D2>A2:A6,D2<B2:B6)),TRUE,FALSE)
This will give you if there is any match or not.
For the number of rows count that match -
=ROWS((FILTER(A2:B6, D2>A2:A6,D2<B2:B6)))
Alomsot =IF(Q2>R2,IF(AND($X$16>HOUR(Q2),$X$16<(HOUR(R2)+12)),1,0),IF(AND(HOUR($X$14)>=HOUR(Q2),HOUR($X$14)<=HOUR(R2)),1,0))

Resources