How to make the matrix caculating faster? - iphone

Hello guys:
I have to project many points before drawing them on a frame.
my codes are blow:
-(Coordination*)xyWorldToDev:(Coordination*)pt isIphoneYAxis:(BOOL)isIphoneYAxis{
CGPoint tmpPoint=CGPointApplyAffineTransform(CGPointMake(pt.x,pt.y),worldToDevMatrix);
Coordination *resultPoint=[[[Coordination alloc]initWithXY:tmpPoint.x withY:(isIphoneYAxis)?(sscy-tmpPoint.y):tmpPoint.y]autorelease];
return resultPoint; }
-(Coordination*)xyDevTo3D:(Coordination*)cPt{
double x=0.0,y=0.0;
double divide=1+m_cView3DPara.v*cPt.y;
x=(m_cView3DPara.a*cPt.x+m_cView3DPara.b*cPt.y+m_cView3DPara.e)/divide;
y=(m_cView3DPara.d*cPt.y+m_cView3DPara.f)/divide;
return [[[Coordination alloc]initWithXY:x withY:sscy-y]autorelease];
}
-(Coordination*)transformWorldTo3D:(Coordination*)pt{
return [self xyDevTo3D:[self xyWorldToDev:pt isIphoneYAxis:NO]];
}
Therefore,the method "-(Coordination*)transformWorldTo3D:(Coordination*)pt " is called hundreds times because projecting.
But i found it is very very SLOW while calling transformWorldTo3D!
Is there another way to accelerate it? Or using another framework which could caculate the projecting value faster?

Object allocations are expensive (relative to arithmetic operations); and it appears that you're doing 2 alloc-init-autorelease sequences for every point.
My first suggestion would be to try to do some of this work with CGPoints and avoid the allocations.
(Actually, that's my second suggestion: my first is to profile the code to see where the time is being spent.)

Related

HERE API:Swift. Wierd behaviour : Loops in a route - Creating a route based on GPS trace creates loops. / passthrough waypoints

im trying to create a route that follows a gps trace i provide.
The gps trace is cleaned up and it has no loops in it and is in correct order.
I checked it with other services.
It has 1920 points.
You can find the trace here GPX Files
Sadly if i create a route based on provided sdk example (github) i get loops in my path.
I was hoping you could help me to solve following problems:
how do i avoid loops while creating route by using HERE ios Swift SDK
how do i set route options is such way to follow provided point array and not create a fastest or balanced route.
Since i could not find those functions in Ios sdk i used additional REST API to filter the route a bit to remove all points that were not matched correctly according to here maps... before drawing the route.. ie everything with low probability, warnings, big distance to the road... yet the result is still not good. Here is a cleaned up file.. the file is being created after the original was maped / run once through HERE Maps. In this file all points that have low confidence or produce warnings or have big distance to original points .. are removed. This is the one i use to create a route and it still have the same issues like loops and weird turns.
Thank you very much in advance!
BR.
So far i have this code:
private lazy var router = NMACoreRouter()
#objc func do_routing_stuff( gps_trace :[NMAWaypoint]) {
var stops = [Any]()
stops = gps_trace
let routingMode = NMARoutingMode(routingType: .fastest,
transportMode: .car,
routingOptions: .avoidHighway)
// Trigger the route calculation
router.calculateRoute(withStops: stops ,
routingMode: routingMode)
{ [weak self] routeResult, error in
guard error == .none else {
self?.showMessage("Error:route calculation returned error code \(error.rawValue)")
return
}
guard let result = routeResult, let routes = result.routes, routes.count > 0 else {
self?.showMessage("Error:route result returned is not valid")
return
}
// Let's add the 1st result onto the map
self?.route = routes[0]
self?.updateMapRoute(with: self?.route)
// self?.startNavigation()
}
}
private func updateMapRoute(with route: NMARoute?) {
// remove previously created map route from map
if let previousMapRoute = mapRoute {
mapView.remove(mapObject:previousMapRoute)
}
guard let unwrappedRoute = route else {
return
}
mapRoute = NMAMapRoute(unwrappedRoute)
mapRoute?.traveledColor = .clear
_ = mapRoute.map{ mapView?.add(mapObject: $0) }
// In order to see the entire route, we orientate the
// map view accordingly
if let boundingBox = unwrappedRoute.boundingBox {
geoBoundingBox = boundingBox
mapView.set(boundingBox: boundingBox, animation: .linear)
}
}
in comparison same route presented with leaflet maps.
I believe the problem you have is that you are feeding the Routing API a large number of waypoints, all of which are in close proximity to each other.
You have almost 2000 waypoints in your GPX file (and ~1300 in your cleaned one). Each of these waypoints is less than 10 meters distance from their closest neighbors. This is not the type of data that the Routing API is really designed to work with.
I've experimented with your GPX Trace and I have come up with the following solution: simply skip a bunch of coordinates in your trace.
First, clean up your trace using the Route Matching API (which I believe you have been doing).
Second, pick the first trkpt in the GPX file as your first waypoint for the Routing call. Then skip the next 20 points. Pick the following trkpoint as the second waypoint. Repeat this until you are at the end of the file. Then add the last trkpt in the trace as the final waypoint.
Then call the Routing API and you should get a good match between your trace and your route, without any loops or other weird routing artefacts.
Some notes:
I have picked 20 as the number of traces to skip, because this would put about 200m in between each waypoint. That should be close enough to ensure that the Routing API does not deviate too much from the traced route. For larger traces you may wish to increase that number. For traces in urban environments with lots alternate routes, you may want to use a smaller number.
It's important to clean the data with the Route Matching API first, to avoid picking outliers as waypoints.
Also, you may not wish to use the "avoidHighways" option. Given your use case, there doesn't seem to be a benefit and I could see it causing additional problems.
By now you probably worked it out, but your waypoints are likely landing on bridges or tunnels that are along your route but not on the road you want. I.e. the waypoint is intended to be on the road under the bridge but the routing engine perceives that you want to drive on the bridge.
The routing engine is looping around those roads to drive you on that waypoint on the bridge or in the tunnel.
There is no simple solution to this that I have found.

CCBezierTo easeout

Working in Objective-c at the moment.
I am drawing a path for my sprite to follow and it all seems to be working fine but i just had one question that didnt seem to be answered anywhere.
My first two points in the Bezier are rather close together in relation to the third point and when my sprite animates along this path it seems like it is being eased in to the animation with an abrupt stop at the end.
Is there a way to control this i'd like to have the animation be one consistent speed or possibly be eased out?
id bezierForward = [CCBezierTo actionWithDuration:totalDistance/300.f bezier:bezier];
[turkey runAction:bezierForward];
Give this a try:
id bezierForward = [CCBezierTo actionWithDuration:totalDistance/300.f bezier:bezier];
id easeBezierForward = [CCEaseOut actionWithAction:bezierForward rate:2.0]
[turkey runAction:easeBezierForward];
You will want to play with the rate value to see what ends up looking best to you. You may have to try out some of the other CCEaseOut options like CCEaseSineOut
Link: Cocos2d Ease Actions Guide
Should probably be something like this, according to the docs:
id bezierForward = [CCEaseOut actionWithDuration:totalDistance/300.f bezier:bezier];
[turkey runAction:bezierForward];
As stated in the docs:
Variations
CCEaseIn: acceleration at the beginning
CCEaseOut: acceleration at the end
CCEaseInOut: acceleration at the beginning / end

NSMutableArray Difficulty

If you wanna see the code Im having problem with, here is the link:
Code
My question is connected with my past question.
I'm really having problem with my NSMutableArray, I'm currently using iCarousel for my slotMachine object(slot1 and slot2). My app works this way:
From PhotoViewController I made a view that has thumbnail images, then assign its frame with button. So if 1 image was pressed, it will save that integer via NSUserDefaults.
Then I will retrieve it in my carouselViewController
Im thinking of adjusting the array but I can't.
I also have tried my question here:
Comparing with NSMutableArray
If only I can do it the same as Array 2 it would be much easy, but still not working.
(ADDITIONAL INFO:)
I have done it this way, have a Viewcontroller that contains the UIImageView with a button in it, so when the user taps it, my CustomPicker pops up. My CustomPicker contains the image on what the user have picked on the camera roll. So each button has a specific value sent to my iCarouselView using NSUserDefaults. carousel1 for First slot and carousel2 for Second slot.
Here is what I wanna do: I want to forcefully make it stop to the index the user picks. (Which Im doing in my carouselDidEndScrollingAnimtaion)
In my carouselDidEndScrollingAnimation method i tested all of my condition(individually) it works perfectly in terms of comparing.
Then when I combine the conditions, the first Two comparison or STOP is RIGHT, but the next two are always wrong. Or sometimes Got mixed up.
I need to scroll the two specific indexes/integer which was User Picked( I already done that) was able to scroll 2 pairs of them but then the next two were always wrong because I think there indexes were adjusting.
PICTURES:
Image Below is my PhotoViewController which contained the Comparing Stage SETTING of my game.UIImageVIew with UIButton.Image that will be put in the number according to it will be Forcefully and should be forcefully shown.
When my iCarousel start then it stops for example in the image below(Which is not the same as the above):
Will be forcefully scroll to the inputted image in the PhotoViewController
Into:
Summary:
Its like this. I have a settingsView from there, I will import my images(Multiple) for Slot1 & Slot2.
Then in another View the PhotoViewController that is where the image above is shown. THe first column corresponds to 1st slot followed by the 2nd slot. if a view is pressed (for example No. 1 of Slot 1 it will load a thumbnail of images loading the images picked from Picker for the Slot 1.
You will have to do it 4 times(pair) ----> The displayed here I get their indexes via NSUserDefaults via button.tag then send to iCarouselView.
Then when you are done (pressed Done button) it will go to iCarouselView then, as shown above thats the view of it.
When pressed it will spin for couple of seconds, then when finished but not stop at the user picked in the PhotoView it will forcefully scroll to that index.
QUESTION:
Is there a way to make my array or my iCarousel.view not adjust their indexes when Im deleting. To still retain my indexes the right way. Or are there other solution like adjusting my array, the same as adjusting my PhotoViewController picked indexes too. Because I think that when my array retain their indexes even deleting I would be able to solve this problem. But still can't.
Hope you understand my question.
Is there a way to make my array or my iCarousel.view not adjust their indexes when Im deleting. To still retain my indexes the right way. Or are there other solution like adjusting my array, the same as adjusting my PhotoViewController picked indexes too. Because I think that when my array retain their indexes even deleting I would be able to solve this problem. But still can't.
The only way you have to modify the way iCarousel manages its indexes is by modifying the code. Indeed, if you look at the removeViewAtIndex method in iCarousel.m, you will see that indexes are managed through an NSDictionary, and at the moment of deleting, the dictionary is rearranged (items are reordered). You could take that method:
- (void)removeViewAtIndex:(NSInteger)index
{
NSMutableDictionary *newItemViews = [NSMutableDictionary dictionaryWithCapacity:[itemViews count] - 1];
for (NSNumber *number in [self indexesForVisibleItems])
{
NSInteger i = [number integerValue];
if (i < index)
{
[newItemViews setObject:[itemViews objectForKey:number] forKey:number];
}
else if (i > index)
{
[newItemViews setObject:[itemViews objectForKey:number] forKey:[NSNumber numberWithInteger:i - 1]];
}
}
self.itemViews = newItemViews;
}
You could apply the same logic to your array, so that the carousel and your array keep in sync. Of course, if you store the indexes somewhere (slot1/slot2/slot2/slot4?), you should also update their values after removing an element.
On the other hand, I think that what you are asking here is how to do something that you believe would solve the problem you have, but you are not really explaining what the problem is. Indeed, if I understand you correctly, what you do is:
spinning the carousel;
when the carousel stops, if it is not by chance on the desired item, you "force" it to scroll to that item.
There is no reason why this should not work after deleting some elements (unless iCarousel has some bugs, then the solution would be catching the bug). The only part is knowing which index is the one you would like to move to.
As a suggestion, I would start off by simplifying your delegate carouselDidEndScrollingAnimation method. Indeed, your carouselDidEndScrollingAnimation has a parameter called carousel, well, I think this is the only carousel you should ever be referring to in that method. If you don't see it, this is the reasoning: each of your carousel will stop scrolling and the carouselDidEndScrollingAnimation will be called; so that method will be called twice. Each time that method is executed you will modify the state of both carousel1 and carousel2 (by calling scrollToItemAtIndex); therefore, on each carousel you will call scrollToItemAtIndex twice.
This does no sound very correct to me. So you should find a way to scroll only carousel1 when carouselDidEndScrollingAnimation is called for carousel1 and to scroll only carousel2 when carouselDidEndScrollingAnimation is called for carousel2.
More generally, another point I would like to raise is that the idea of:
letting a carousel stop;
scrolling it again so that it reaches the desired position;
does not seem the best implementation possible since the user would see the carousel stopping and then starting over again.
The way I would approach this is by modifying directly iCarousel implementation so that it supports this specific behavior you need.
Concretely, give a look at the step method in iCarousel.m. This is called at each frame to produce the carousel animation. Now, in this method there is decelerating branch:
else if (decelerating)
{
CGFloat time = fminf(scrollDuration, currentTime - startTime);
CGFloat acceleration = -startVelocity/scrollDuration;
CGFloat distance = startVelocity * time + 0.5f * acceleration * powf(time, 2.0f);
scrollOffset = startOffset + distance;
[self didScroll];
if (time == (CGFloat)scrollDuration)
{
decelerating = NO;
if ([delegate respondsToSelector:#selector(carouselDidEndDecelerating:)])
{
[delegate carouselDidEndDecelerating:self];
}
if (scrollToItemBoundary || (scrollOffset - [self clampedOffset:scrollOffset]) != 0.0f)
{
if (fabsf(scrollOffset/itemWidth - self.currentItemIndex) < 0.01f)
{
//call scroll to trigger events for legacy support reasons
//even though technically we don't need to scroll at all
[self scrollToItemAtIndex:self.currentItemIndex duration:0.01];
}
else
{
[self scrollToItemAtIndex:self.currentItemIndex animated:YES];
}
}
else
{
CGFloat difference = (CGFloat)self.currentItemIndex - scrollOffset/itemWidth;
if (difference > 0.5)
{
difference = difference - 1.0f;
}
else if (difference < -0.5)
{
difference = 1.0 + difference;
}
toggleTime = currentTime - MAX_TOGGLE_DURATION * fabsf(difference);
toggle = fmaxf(-1.0f, fminf(1.0f, -difference));
}
}
}
and you see that when the carousel stops decelerating, it is scrolled again. This is exactly the same as you are doing, so you might find a way to modify this code and have the carousel scrolls exactly to the index you need. In this way you would get a far smoother spinning of the carousel.
Hope this helps and apologies for the lengthy reply.
Its a little difficult to know what the issue is here. Are you using a single NSMutableArray for the images and using the NSUserDefaults value to get the object at the index in the array?
Im not 100% sure on what is happening. What does the user do(and in what view) and what is triggered after that(which view is presented).
Are you trying to stop the "spinning" images on the image that is the same as the one picked from the previous view?
According to your images above, the images are off by a single index. Is this the case every time? Maybe there is an issue with your fetching from the array.
If you give me some more info I can help.
I looked through the code you pasted again and I think this might be your issue
if (twoSlot1 > [(UIImageView*)[self.carousel2 currentItemView] tag]){
[self.carousel1 scrollToItemAtIndex:(-twoSlot1)-2 duration: 3.5f];
} else {
[self.carousel1 scrollToItemAtIndex:-twoSlot1 duration: 3.5f];
}
On all other code blocks like that you have this where you call each carousel. In the above code you call carousel 1 twice.
if (slot2 > [(UIImageView*)[self.carousel1 currentItemView] tag]){
[self.carousel1 scrollToItemAtIndex:(-slot2)-2 duration: 3.0f];
} else {
[self.carousel1 scrollToItemAtIndex:-slot2 duration: 3.0f];
}
if (twoSlot2 > [(UIImageView*)[self.carousel2 currentItemView] tag]){
[self.carousel2 scrollToItemAtIndex:(-twoSlot2)-2 duration: 3.5f];
} else {
[self.carousel2 scrollToItemAtIndex:-twoSlot2 duration: 3.5f];
}
You call self.carousel1 when you should be calling number 2.
Is this correct?
Referring to your question. You want an array that does not change its members' indexes when a member is deleted from the array.
I guess you could use an NSMutableDictionary. It is an associative array so to say, where the indexes are of your choice and they remain unchanged when you delete a member from in between.
You may still use 0..n as your Index. You can still use some methods that you are familiar with from NSArray, such as count. You can use an enumerator to go through all members of the dictionary. On the other hand you can still use your for-loops as you are used to use them with arrays. Just be prepared that a) objectForKey:i may return nil if the key/index does not exist (e.g. was deleted) and that count retuns the number of the objects but not the highest index+1 as it does with arrays.
Not sure if I understand completely, but when one of the elements in your mutable array is deleted, rather than just deleting it, maybe insert it with another "dummy" place holder object? That way your indexes won't change at all when a delete occurs
I'm having a hard time understanding your overall problem, but from what I can gather the crux of your question is this:
Is there a way to make my array or my iCarousel.view not adjust their indexes when Im deleting.
I don't know whether it will solve your bigger issue, but using an NSMutableDictionary to simulate an array should allow you to do this. You can simply use the indices as the keys to the dictionary, and then when you remove the item associated with an index, no other indices will be adjusted as a result. For example:
NSMutableDictionary *arrayDict = [[NSMutableDictionary alloc] init];
[arrayDict setValue:foo forKey:[NSNumber numberWithInt:[arrayDict count]]];
[arrayDict setValue:bar forKey:[NSNumber numberWithInt:[arrayDict count]]];
[arrayDict setValue:fooBar forKey:[NSNumber numberWithInt:[arrayDict count]]];
And then you can access the object an at index with [arrayDict objectForKey:[NSNumber numberWithInt:index]].
Note that using an NSNumber for the key parameter of setValue:forKey: will generate a warning, but you can safely ignore this (or use the string representation if it bothers you).

insertion sort on a singly linked list

Am i right in thinking that it is not possible to perform insertion sort on a singly linked list?
My reasoning: assuming that insertion sort by definition means that, as we move to the right in the outer loop, we move to the left in the inner loop and shift values up (to the right) as required and insert our current value when done with the inner loop. As a result an SLL cannot accomodate such an algorithm. Correct?
Well, I'd sound like the Captain Obvious, but the answer mostly depends on whether you're ok with keeping all iterations directed the same way as elements are linked and still implementing the proper sorting algorithm as per your definition. I don't really want to mess around your definition of insertion sorting, so I'm afraid you'd really have to think yourself. At least for a while. It's an homework anyway... ;)
Ok, here's what I got just before closing the page. You may iterate over an SLL in reversed direction, but this would take n*n/2 traversals to visit all the n elements. So you're theoretically okay with any traversal directions for your sorting loops. Guess it pretty much solves your question.
It is doable and is an interesting problem to explore.
The core of insertion sort algorithm is creating a sorted sequence with the first one element and extending it by adding new element and keeping the sequence is still sorted until it contains all the input data.
Singly linked list can not be traversed back, but you can always start from it's head to search the position for the new element.
The tricky part is when inserting node i before node j, you must handle their neighbor relationship well(I mean both node i and j's neighbor needs to be taken care of).
Here is my code. I hope it useful for you.
int insertSort(Node **pHead)
{
Node *current1 = (*pHead)->next;
Node *pre1 =*pHead;
Node *current2= *pHead;
Node *pre2=*pHead;
while(NULL!=current1)
{
pre2=*pHead;
current2=*pHead;
while((current2->data < current1->data))
{
pre2 = current2;
current2 = current2->next;
}
if(current2 != current1)
{
pre1->next=current1->next;
if(current2==*pHead)
{
current1->next=*pHead;
*pHead = current1;
}
else
{
pre2->next = current1;
current1->next = current2;
}
current1 = pre1->next;
}
else
{
pre1 = pre1->next;
current1 = current1->next;
}
}
return 0;
}

IPhone: different system timers?

I have been using mach_absolute_time() for all my timing functions so far. calculating how long between frames etc.
I now want to get the exact time touch input events happen using event.timestamp in the touch callbacks.
the problem is these two seem to use completely different timers. sure, you can get them both in seconds, but their origins are different and seemingly random...
is there any way to sync the two different timers?
or is there anyway to get access to the same timer that the touch input uses to generate that timestamp property? otherwise its next to useless.
Had some trouble with this myself. There isn't a lot of good documentation, so I went with experimentation. Here's what I was able to determine:
mach_absolute_time depends on the processor of the device. It returns ticks since the device was last rebooted (otherwise known as uptime). In order to get it in a human readable form, you have to modify it by the result from mach_timebase_info (a ratio), which will return billionth of seconds (or nanoseconds). To make this more usable I use a function like the one below:
#include <mach/mach_time.h>
int getUptimeInMilliseconds()
{
static const int64_t kOneMillion = 1000 * 1000;
static mach_timebase_info_data_t s_timebase_info;
if (s_timebase_info.denom == 0) {
(void) mach_timebase_info(&s_timebase_info);
}
// mach_absolute_time() returns billionth of seconds,
// so divide by one million to get milliseconds
return (int)((mach_absolute_time() * s_timebase_info.numer) / (kOneMillion * s_timebase_info.denom));
}
Get the initial difference between two i.e
what is returned by mach_absolute_time() initally when your application starts and also get the event.timestamp initially at the same time...
store the difference... it would remain same through out the time your application runs.. so you can use this time difference to convert one to another...
How about CFAbsoluteTimeGetCurrent?