How to Create a Dynamic CGPoint** array - ios

I have a few maps (tilemaps made with Tiled QT) and I would like to create a CGpoint **array based on the objects groups of those maps (I call them Waypoints).
Each maps can have a few set of waypoints that I call path.
//Create the first dimension
int nbrOfPaths = [[self.tileMap objectGroups] count];
CGPoint **pathArray = malloc(nbrOfPaths * sizeof(CGPoint *));
Then for the second dimension
//Create the second dimension
int pathCounter = 0;
while ((path = [self.tileMap objectGroupNamed:[NSString stringWithFormat:#"Path%d", pathCounter]])) {
int nbrOfWpts = 0;
while ((waypoint = [path objectNamed:[NSString stringWithFormat:#"Wpt%d", nbrOfWpts]])) {
nbrOfWpts++;
}
pathArray[pathCounter] = malloc(nbrOfWpts * sizeof(CGPoint));
pathCounter++;
}
Now I want to fill up the pathArray
//Fill the array
pathCounter = 0;
while ((path = [self.tileMap objectGroupNamed:[NSString stringWithFormat:#"Path%d", pathCounter]]))
{
int waypointCounter = 0;
//Get all the waypoints from the path
while ((waypoint = [path objectNamed:[NSString stringWithFormat:#"Wpt%d", waypointCounter]]))
{
pathArray[pathCounter][waypointCounter].x = [[waypoint valueForKey:#"x"] intValue];
pathArray[pathCounter][waypointCounter].y = [[waypoint valueForKey:#"y"] intValue];
NSLog(#"x : %f & y : %f",pathArray[pathCounter][waypointCounter].x,pathArray[pathCounter][waypointCounter].y);
waypointCounter++;
}
pathCounter++;
}
When I NSLog(#"%#",pathArray), it shows me the entire pathArray will the x and y.
HOWEVER 2 problems :
The y value is never correct (the x value is correct and my tilemap.tmx is correct too)
<object name="Wpt0" x="-18" y="304"/> <-- I get x : -18 and y :336 with NSLog
<object name="Wpt1" x="111" y="304"/> <-- I get x : 111 and y :336
<object name="Wpt2" x="112" y="207"/> <-- I get x : 112 and y :433
I get a EX_BAD_ACCESS at the end of the NSLog
EDIT
Thank you about the NSLog(%#) concerning CGPoint.
However, I get the y value with this line (in the ugly loop):
NSLog(#"x : %f & y : %f",pathArray[pathCounter][waypointCounter].x,pathArray[pathCounter][waypointCounter].y);

First of all, you can't NSLog CGPoint like that because it is not an object. %# expects an objective c object to send a description message to.
Secondly, you can use an NSValue wrapper and then use NSMutableArray as you would with any other object. Is there a reason you don't want to do that? You can add arrays inside other arrays as you are doing.

Regarding the first problem:
The y value is never correct (the x value is correct and my tilemap.tmx is correct too)
Have you noticed that if you add the y values from tile map and from NSLog they always add up to 640? Then you better check if tilemap y-coordinate is top-to-bottom as oppose to CGPoint's bottom-to-top. Then you can always do 640 - y to convert the y-coordinate between the two coordinate systems.

Related

Find longest path between root node and any child

I have an array of elements, some of whom have children, who have children in turn and so on. I know the direct children of each element, and have a list of all descendents for each element.
-(NSMutableArray *)descendents:(Element *)e {
NSMutableArray * descendents = [NSMutableArray new];
for (NSString * uID in e.children){
[descendents addObject:uID];
Element * k = elements[uID][#"element"];
[descendents addObjectsFromArray:[self descendents:k]];
}
return descendents;
}
I can determine the root element by comparing the total number of descendents for each element. I can find the shortest route between the root and any given element given this:
-(int)find:(NSString *)uniqueID forElement:(Element *)e {
int distance = 0;
if ([e.children containsObject:uniqueID]){ //immediate child
distance ++; //increment distance
return distance; //return
} else if ([e.descendents containsObject:uniqueID]){ //grand child etc
distance ++;
for (NSString * uID in e.children){
Element * k = elements[uID][#"element"];
distance += [self find:uniqueID forElement:k];
return distance;
}
}
return 0;
}
What I want to do is find the longest distance between an element and the root. I'm thinking about going back up the tree from elements with zero children or adding an array of distances between elements in the mapping function. Struggling as to the cleanest approach - any ideas?
EDIT:
solution based on user3290797's answer below, tracking reference to max number of parents:
-(int)parentHeight:(NSString *)uID {
int maxHeight = 0;
Element * e = elements[uID][#"element"];
for (NSString * parentID in e.parents){
int height = [self parentHeight:parentID];
maxHeight = (height > maxHeight) ? height : maxHeight;
}
return maxHeight + 1;
}
The longest distance between an element and the root is called the height (or depth) of the tree.
One way to find it is to recursively traverse the tree and calculate the height of every node as the maximum of its children's heights plus one.
In pseudocode:
function height(node) {
maxChildHeight = 0
for(child in node.children) {
h = height(child)
if(h > maxChildHeight) {
maxChildHeight = h
}
}
return maxChildHeight + 1
}
If not a lot of nodes, calculate each distance and assign an ID for each , then check the longest of them , this is slow but works hahaha

convert NSMutableArray to CGPoint Array

the typical answer will be "you can convert it to nsvalue and then use [element CGPointValue];
but in my case i need to generate array of type CGPoint , as i need it in a built in function below :
static CGPathRef createClosedPathWithPoints(const CGPoint *points, size_t count) {
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddLines(path, NULL, points, count);
CGPathCloseSubpath(path);
return path;
}
so , i need to pass the exact datatype , as i can't parse it element by element , or i need a way to everytime the user make a specific action , i add it's CGPoint to array of CGPoints :((
thanks in advance
edit :
i have tried malloc and making c array but the result of the function was not desirable , i tested and made infinity for loop to that malloc array , and it's too large not just like the size i sat , and contain garbage so the result went wrong
this is the mutable array
pointToPoints = [NSMutableArray new];
[pointToPoints addObject:[NSValue valueWithCGPoint:tempPoint] ];
Here is something that will create a closed path from an NSArray of NSValue created with CGPoint using the code your provided:
BOOL isCGPoint(NSValue *value){
return value && strcmp([value objCType], #encode(CGPoint)) == 0;
}
- (CGPathRef) closedPathFromPointArray:(NSArray *)points{
CGMutablePathRef path = CGPathCreateMutable();
if(points.count){
CGPoint origin = ((NSValue *)points[0]).CGPointValue;
CGPathMoveToPoint (path, NULL, origin.x, origin.y);
// see https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGPath/#//apple_ref/c/func/CGPathAddLines
for(NSValue *value in points){
CGPathAddLineToPoint (path, NULL, value.CGPointValue.x, value.CGPointValue.y);
}
}
CGPathCloseSubpath(path);
return path;
}
As you see, you don't really need malloc, or even creating a C array of CGPoint. This assumes you only need this array for creating the closed path.
Two extra things of note:
See the commented link for CGPathAddLines, as it describes how CGPathAddLines works internally. This gives you the hint about how to go about this.
The isCGPoint function is included so you can test if a given NSValue instance was actually created using [NSValue valueWithCGPoint:]. My previous answer checked this, but I thought it was ooverkill to check everywhere. In any case, it's included here for didactic purposes.
CGPoint *points = malloc(sizeof(CGPoint) * mutableArrayOfPoints.count);
for (int i = 0; i < mutableArrayOfPoints.count; i++) {
points[i] = [mutableArrayOfPoints[i] pointValue];
}
The above is from memory. I haven't used malloc() in ages, so you may need to adjust syntax.

Objective C " * " syntax and usage

I am re-writing the particle filter library of iOS in Swift from Objective C which is available on Bitbucket and I have a question regarding a syntax of Objective C which I cannot understand.
The code goes as follows:
- (void)setRssi:(NSInteger)rssi {
_rssi = rssi;
// Ignore zeros in average, StdDev -- we clear the value before setting it to
// prevent old values from hanging around if there's no reading
if (rssi == 0) {
self.meters = 0;
return;
}
self.meters = [self metersFromRssi:rssi];
NSInteger* pidx = self.rssiBuffer;
*(pidx+self.bufferIndex++) = rssi;
if (self.bufferIndex >= RSSIBUFFERSIZE) {
self.bufferIndex %= RSSIBUFFERSIZE;
self.bufferFull = YES;
}
if (self.bufferFull) {
// Only calculate trailing mean and Std Dev when we have enough data
double accumulator = 0;
for (NSInteger i = 0; i < RSSIBUFFERSIZE; i++) {
accumulator += *(pidx+i);
}
self.meanRssi = accumulator / RSSIBUFFERSIZE;
self.meanMeters = [self metersFromRssi:self.meanRssi];
accumulator = 0;
for (NSInteger i = 0; i < RSSIBUFFERSIZE; i++) {
NSInteger difference = *(pidx+i) - self.meanRssi;
accumulator += difference*difference;
}
self.stdDeviationRssi = sqrt( accumulator / RSSIBUFFERSIZE);
self.meanMetersVariance = ABS(
[self metersFromRssi:self.meanRssi]
- [self metersFromRssi:self.meanRssi+self.stdDeviationRssi]
);
}
}
The class continues with more code and functions which are not important and what I do not understand are these two lines
NSInteger* pidx = self.rssiBuffer;
*(pidx+self.bufferIndex++) = rssi;
Variable pidx is initialized to the size of a buffer which was previously defined and then in the next line the size of that buffer and buffer plus one is equal to the RSSI variable which is passed as a parameter in the function.
I assume that * has something to do with reference but I just can't figure out the purpose of this line. Variable pidx is used only in this function for calculating trailing mean and standard deviation.
Let explain those code:
NSInteger* pidx = self.rssiBuffer; means that you are getting pointer of the first value of the buffer.
*(pidx+self.bufferIndex++) = rssi; means that you are setting the value of the buffer at index 0+self.bufferIndex to rssiand then increase bufferIndex by 1. Thanks to #Jakub Vano point it out.
In C++, it will look like that
int self.rssiBuffer[1000]; // I assume we have buffer like that
self.rssiBuffer[self.bufferIndex++] = rssi

Accelerate framework "sign" function

I'm trying to find a super fast way of getting the sign of each value in a vector. I was hoping to find a function in the accelerate framework to do this, but couldn't find one. Here's what it would do:
float *inputVector = .... // some audio vector
int length = ...// length of input vector.
float *outputVector = ....// result
for( int i = 0; i<length; i++ )
{
if( inputVector[i] >= 0 ) outputVector[i] = 1;
else outputVector[i] = -1;
}
Ok, I think I've found a way...
vvcopysignf() "Copies an array, setting the sign of each value based on a second array."
So, one method would be to make an array of 1s, then use this function to change the sign of the 1s based on an input array.
float *ones = ... // a vector filled with 1's
float *input = .... // an input vector
float *output = ... // an output vector
int bufferSize = ... // size of the vectors;
vvcopysignf(output, ones, input, &bufferSize);
//output now is an array of -1s and 1s based the sign of the input.

Find nearest float in array

How would I get the nearest float in my array to a float of my choice? Here is my array:
[1.20, 1.50, 1.75, 1.95, 2.10]
For example, if my float was 1.60, I would like to produce the float 1.50.
Any ideas? Thanks in advance!
You can do it by sorting the array and finding the nearest one.
For this you can use sortDescriptors and then your algorithm will go.
Even you can loop through, by assuming first as the required value and store the minimum absolute (abs()) difference, if next difference is lesser than hold that value.
The working sample, however you need to handle other conditions like two similar values or your value is just between two value like 2 lies between 1 and 3.
NSArray *array = #[#1.20, #1.50, #1.75, #1.95, #2.10];
double my = 1.7;
NSNumber *nearest = array[0];
double diff = fabs(my - [array[0] doubleValue]);
for (NSNumber *num in array) {
double d = [num doubleValue];
if (diff > fabs(my - d) ) {
nearest = num;
diff = my - d;
}
}
NSLog(#"%#", nearest);

Resources