EDIT: PROBLEM SOLVED. This code works properly !
I translated this python code Shortest distance between two line segments (answered by Fnord) to Objective-C in order to find the shortest distance between two line segments. However the distances are incorrect. Could you please help me find what is wrong?
Matrix.h:
#import <Cocoa/Cocoa.h>
#interface Matrix : NSObject
#property NSUInteger m;
#property NSUInteger n;
#property NSMutableArray *rows;
- (id)initWithSizeM:(NSUInteger)m N:(NSUInteger)n;
- (CGFloat)determinant3x3;
#end
Matrix.m:
#import <Cocoa/Cocoa.h>
#import "Matrix.h"
#implementation Matrix;
- (id)initWithSizeM:(NSUInteger)m N:(NSUInteger)n {
self = [super init];
_m = m;
_n = n;
_rows = [NSMutableArray new];
for (int i = 0; i < m; i ++) {
[_rows addObject:[NSMutableArray new]];
for (int j = 0; j < n; j ++) {
CGFloat value = 0.0;
[_rows[i] addObject:[NSNumber numberWithFloat:value]];
}
}
return self;
}
- (CGFloat)determinant3x3 {
CGFloat a = [_rows[0][0] floatValue];
CGFloat b = [_rows[0][1] floatValue];
CGFloat c = [_rows[0][2] floatValue];
CGFloat d = [_rows[1][0] floatValue];
CGFloat e = [_rows[1][1] floatValue];
CGFloat f = [_rows[1][2] floatValue];
CGFloat g = [_rows[2][0] floatValue];
CGFloat h = [_rows[2][1] floatValue];
CGFloat i = [_rows[2][2] floatValue];
return a*e*i + b*f*g + c*d*h - c*e*g - b*d*i - a*f*h;
}
#end
PointCartesian.h:
#import <Cocoa/Cocoa.h>
#import "Vector.h"
#class Vertex;
#interface PointCartesian: NSObject
#property CGFloat x;
#property CGFloat y;
#property CGFloat z;
#property NSString *name;
- (id)initWithCoordinatesX:(CGFloat)x Y:(CGFloat)y Z:(CGFloat)z;
- (Vector*)toVector;
+ (CGFloat)shortestDistanceBetweenTwoSegmentsA0:(PointCartesian*)a0 A1:(PointCartesian*)a1 B0:(PointCartesian*)b0 B1:(PointCartesian*)b1;
#end
PointCartesian.m:
#import <Cocoa/Cocoa.h>
#import "PointCartesian.h"
#import "Vector.h"
#import "Matrix.h"
#implementation PointCartesian;
- (id)initWithCoordinatesX:(CGFloat)x Y:(CGFloat)y Z:(CGFloat)z {
_x = x;
_y = y;
_z = z;
return self;
}
- (Vector*)toVector {
return [[Vector alloc] initWithX:_x Y:_y Z:_z];
}
+ (CGFloat)shortestDistanceBetweenTwoSegmentsA0:(PointCartesian*)a0 A1:(PointCartesian*)a1 B0:(PointCartesian*)b0 B1:(PointCartesian*)b1 {
BOOL clampA0 = YES;
BOOL clampA1 = YES;
BOOL clampB0 = YES;
BOOL clampB1 = YES;
Vector *A = [Vector vectorFromA:a0 B:a1];
Vector *B = [Vector vectorFromA:b0 B:b1];
CGFloat magA = [A length];
CGFloat magB = [B length];
Vector *_A = [[Vector alloc] initWithX:A.x/magA Y:A.y/magA Z:A.z/magA];
Vector *_B = [[Vector alloc] initWithX:B.x/magB Y:B.y/magB Z:B.z/magB];
Vector *cross = [Vector crossProductA:_A B:_B];
CGFloat denom = pow([cross length], 2);
if (denom == 0) {
CGFloat d0 = [Vector dotProductA:_A B:[Vector vectorFromA:a0 B:b0]];
if (clampA0 || clampA1 || clampB0 || clampB1) {
CGFloat d1 = [Vector dotProductA:_A B:[Vector vectorFromA:a0 B:b1]];
if (d0 <= 0 && 0 >= d1) {
if (clampA0 && clampB1) {
if (floor(d0) < floor(d1)) {
return [[Vector vectorFromA:b0 B:a0] length];
}
return [[Vector vectorFromA:b1 B:a0] length];
}
}
if (d0 >= magA && magA <= d1) {
if (clampA1 && clampB0) {
if (floor(d0) < floor(d1)) {
return [[Vector vectorFromA:b0 B:a1] length];
}
return [[Vector vectorFromA:b1 B:a1] length];
}
}
}
return [[[Vector alloc] initWithX:d0*_A.x + a0.x - b0.x Y:d0*_A.y + a0.y - b0.y Z:d0*_A.z + a0.z - b0.z] length];
}
Vector *t = [Vector vectorFromA:a0 B:b0];
Matrix *MA = [[Matrix alloc] initWithSizeM:3 N:3];
MA.rows[0][0] = [NSNumber numberWithFloat:t.x];
MA.rows[0][1] = [NSNumber numberWithFloat:t.y];
MA.rows[0][2] = [NSNumber numberWithFloat:t.z];
MA.rows[1][0] = [NSNumber numberWithFloat:_B.x];
MA.rows[1][1] = [NSNumber numberWithFloat:_B.y];
MA.rows[1][2] = [NSNumber numberWithFloat:_B.z];
MA.rows[2][0] = [NSNumber numberWithFloat:cross.x];
MA.rows[2][1] = [NSNumber numberWithFloat:cross.y];
MA.rows[2][2] = [NSNumber numberWithFloat:cross.z];
Matrix *MB = [[Matrix alloc] initWithSizeM:3 N:3];
MB.rows[0][0] = [NSNumber numberWithFloat:t.x];
MB.rows[0][1] = [NSNumber numberWithFloat:t.y];
MB.rows[0][2] = [NSNumber numberWithFloat:t.z];
MB.rows[1][0] = [NSNumber numberWithFloat:_A.x];
MB.rows[1][1] = [NSNumber numberWithFloat:_A.y];
MB.rows[1][2] = [NSNumber numberWithFloat:_A.z];
MB.rows[2][0] = [NSNumber numberWithFloat:cross.x];
MB.rows[2][1] = [NSNumber numberWithFloat:cross.y];
MB.rows[2][2] = [NSNumber numberWithFloat:cross.z];
CGFloat detA = [MA determinant3x3];
CGFloat detB = [MB determinant3x3];
CGFloat t0 = detA / denom;
CGFloat t1 = detB / denom;
PointCartesian *pA = [[PointCartesian alloc] initWithCoordinatesX:_A.x*t0 + a0.x Y:_A.y*t0 + a0.y Z:_A.z*t0 + a0.z];
PointCartesian *pB = [[PointCartesian alloc] initWithCoordinatesX:_B.x*t1 + b0.x Y:_B.y*t1 + b0.y Z:_B.z*t1 + b0.z];
if (clampA0 || clampA1 || clampB0 || clampB1) {
if (clampA0 && t0 < 0) {
pA = a0;
} else if (clampA1 && t0 > magA) {
pA = a1;
}
if (clampB0 && t1 < 0) {
pB = b0;
} else if (clampB1 && t1 > magB) {
pB = b1;
}
if ((clampA0 && t0 < 0) || (clampA1 && t0 > magA)) {
CGFloat dot = [Vector dotProductA:_B B:[Vector vectorFromA:b0 B:pA]];
if (clampB0 && dot < 0) {
dot = 0;
} else if (clampB1 && dot > magB) {
dot = magB;
}
pB = [[PointCartesian alloc] initWithCoordinatesX:b0.x + _B.x*dot Y:b0.y + _B.y*dot Z:b0.z + _B.z*dot];
}
if ((clampB0 && t1 < 0) || (clampB1 && t1 > magB)) {
CGFloat dot = [Vector dotProductA:_A B:[Vector vectorFromA:a0 B:pB]];
if (clampA0 && dot < 0) {
dot = 0;
} else if (clampA1 && dot > magA) {
dot = magA;
}
pA = [[PointCartesian alloc] initWithCoordinatesX:a0.x + _A.x*dot Y:a0.y + _A.y*dot Z:a0.z + _A.z*dot];
}
}
return [[[Vector alloc] initWithX:pA.x-pB.x Y:pA.y-pB.y Z:pA.z - pB.z] length];
}
#end
Vector.h:
#import <Cocoa/Cocoa.h>
#class PointCartesian;
#interface Vector: NSObject
#property CGFloat x;
#property CGFloat y;
#property CGFloat z;
#property NSString *name;
- (id)initWithX:(CGFloat)x Y:(CGFloat)y Z:(CGFloat)z;
- (CGFloat)length;
- (void)normalize;
+ (Vector*)vectorFromA:(PointCartesian*)a B:(PointCartesian*)b;
- (PointCartesian*)toPoint;
+ (CGFloat)dotProductA:(Vector*)a B:(Vector*)b;
+ (Vector*)crossProductA:(Vector*)a B:(Vector*)b;
#end
Vector.m:
#import <Cocoa/Cocoa.h>
#import "Vector.h"
#import "PointCartesian.h"
#implementation Vector
- (id)initWithX:(CGFloat)x Y:(CGFloat)y Z:(CGFloat)z {
_x = x;
_y = y;
_z = z;
return self;
}
- (CGFloat)length {
return sqrt(pow(_x,2)+pow(_y,2)+pow(_z,2));
}
- (void)normalize {
_x = _x / [self length];
_y = _y / [self length];
_z = _z / [self length];
}
+ (Vector*)vectorFromA:(PointCartesian*)a B:(PointCartesian*)b {
Vector *AB = [[Vector alloc] initWithX:b.x-a.x Y:b.y-a.y Z:b.z-a.z];
return AB;
}
- (PointCartesian*)toPoint {
return [[PointCartesian alloc] initWithCoordinatesX:_x Y:_y Z:_z];
}
+ (CGFloat)dotProductA:(Vector*)a B:(Vector*)b {
return a.x*b.x + a.y*b.y + a.z*b.z;
}
+ (Vector*)crossProductA:(Vector*)a B:(Vector*)b {
return [[Vector alloc] initWithX:a.y*b.z - a.z*b.y Y:a.z*b.x - a.x*b.z Z:a.x*b.y - a.y*b.x];
}
#end
main.m:
#import <Cocoa/Cocoa.h>
#import "PointCartesian.h"
int main(int argc, const char * argv[]) {
PointCartesian *a0 = [[PointCartesian alloc] initWithCoordinatesX:27.83 Y:31.74 Z:-26.60];
PointCartesian *a1 = [[PointCartesian alloc] initWithCoordinatesX:13.43 Y:21.77 Z:46.81];
PointCartesian *b0 = [[PointCartesian alloc] initWithCoordinatesX:77.54 Y:7.53 Z:6.22];
PointCartesian *b1 = [[PointCartesian alloc] initWithCoordinatesX:26.99 Y:12.39 Z:11.18];
CGFloat d = [PointCartesian shortestDistanceBetweenTwoSegmentsA0:a0 A1:a1 B0:b0 B1:b1];
NSLog(#"%f", d);
return NSApplicationMain(argc, argv);
}
output:
2020-06-26 17:57:30.762912+0200 Distance[2235:111429] 15.651394
The distance should be 15.826771412132246 according to the python code in link above.
Related
I'm trying to implement perceptron on Objective-C. Now i'm facing the problem that after some random amount of epochs, when error's tending to its minimum or maximum, network is paralysis, and after some more epochs all weights becomes very big or very small numbers, and output and propagation of network becomes NaN. What could be the problem?
My code is here, the main method is learn:
Neuron.h
#interface Neuron : NSObject <NSCoding>
#property (nonatomic) double output;
#property (strong,nonatomic) NSMutableArray *weights;
#property (nonatomic) double propagation;
#end
Web.h
#import "Neuron.h"
#interface Web : NSObject
#property (strong,nonatomic) NSMutableArray *arrayOfLayers;
-(void)setupWebWithNumberOfNeutrons:(NSInteger)number inputArray:(NSArray*)input;
-(void)addToLearningData:(NSArray *)array;
-(void)saveLearningArrayWithPath:(NSString *)path;
-(void)learn;
-(void)setupWeb;
#end
Web.m
#interface Web() <NSCoding>
#property (nonatomic) NSInteger numberOfHiddenLayerNeutrons;
#property (nonatomic) double output;
#property (nonatomic) double propagation;
#property (nonatomic) double answer;
#property (strong,nonatomic) NSMutableArray *learningArray;
#property (strong,nonatomic) NSMutableArray *learningData;
#property (strong,nonatomic) NSMutableArray *epocheLearningArrays;
#property (strong,nonatomic) NSMutableArray *epocheTestingArrays;
#end
const NSInteger kNumberOfHiddenNeurons = 20;
const NSInteger kNumberOfEpocheLearningArray = 70;
const NSInteger kMaxEpocheCount = 100;
#implementation Web
#pragma mark - Properties
-(NSMutableArray *)learningArray
{
if (!_learningArray) {
_learningArray = [[NSMutableArray alloc] init];
}
return _learningArray;
}
-(NSMutableArray *)learningData {
if (!_learningData) {
_learningData = [NSMutableArray array];
}
return _learningData;
}
-(NSMutableArray *)epocheLearningArrays {
if (!_epocheLearningArrays) {
_epocheLearningArrays = [NSMutableArray array];
}
return _epocheLearningArrays;
}
-(NSMutableArray *)epocheTestingArrays {
if (!_epocheTestingArrays) {
_epocheTestingArrays = [NSMutableArray array];
}
return _epocheTestingArrays;
}
-(NSMutableArray *)arrayOfLayers
{
if (!_arrayOfLayers) {
_arrayOfLayers = [[NSMutableArray alloc] init];
}
return _arrayOfLayers;
}
-(void)addToLearningData:(NSArray *)array
{
[self.learningData addObject:array];
[self saveLearningDataWithPath:nil];
}
#pragma mark - Setup
-(void)setupWeb {
NSMutableArray *arrayOfInputNeurons = [[NSMutableArray alloc] init];
for (int i=0; i < 100; i++) {
Neuron *neuron = [[Neuron alloc] init];
[arrayOfInputNeurons addObject:neuron];
}
[self.arrayOfLayers addObject:arrayOfInputNeurons];
NSMutableArray *arrayOfFirstHiddenLayerNeurons = [[NSMutableArray alloc] init];
for (int i=0; i < kNumberOfHiddenNeurons; i++) {
Neuron *neuron = [[Neuron alloc] init];
[arrayOfFirstHiddenLayerNeurons addObject:neuron];
}
[self.arrayOfLayers addObject:arrayOfFirstHiddenLayerNeurons];
NSMutableArray *arrayOfSeconHiddenLayerNeurons = [[NSMutableArray alloc] init];
Neuron *outputNeuron = [[Neuron alloc] init];
[arrayOfSeconHiddenLayerNeurons addObject:outputNeuron];
[self.arrayOfLayers addObject:arrayOfSeconHiddenLayerNeurons];
[self setRandomWeights];
}
-(void)setupWebWithNumberOfNeutrons:(NSInteger)number inputArray:(NSArray*)input
{
self.output = 1;
NSMutableArray *arrayOfInputNeurons = [[NSMutableArray alloc] init];
for (NSNumber *state in input) {
Neuron *neuron = [[Neuron alloc] init];
neuron.output = state.intValue;
[arrayOfInputNeurons addObject:neuron];
}
[self.arrayOfLayers addObject:arrayOfInputNeurons];
NSMutableArray *arrayOfFirstHiddenLayerNeurons = [[NSMutableArray alloc] init];
for (int i=0; i < number; i++) {
Neuron *neuron = [[Neuron alloc] init];
[arrayOfFirstHiddenLayerNeurons addObject:neuron];
}
[self.arrayOfLayers addObject:arrayOfFirstHiddenLayerNeurons];
NSMutableArray *arrayOfSeconHiddenLayerNeurons = [[NSMutableArray alloc] init];
Neuron *outputNeuron = [[Neuron alloc] init];
[arrayOfSeconHiddenLayerNeurons addObject:outputNeuron];
[self.arrayOfLayers addObject:arrayOfSeconHiddenLayerNeurons];
if (!self.propagation) {
[self setRandomWeights];
}
[self forwardPass];
Neuron *neuron = (Neuron *)self.arrayOfLayers[2][0];
self.answer = -1;
[self calculatePropagation:neuron];
[self backPass];
[self resetWeights];
}
-(void)setRandomWeights
{
for (NSInteger i=0; i<[self.arrayOfLayers count]-1; i++) {
for (Neuron *neuron in self.arrayOfLayers[i]) {
NSMutableArray *weights = [NSMutableArray array];
for (NSInteger j=0; j<[self.arrayOfLayers[i+1] count]; j++) {
[weights addObject:#((((float) rand() / RAND_MAX) * 1) -0.5)];
}
neuron.weights = weights;
}
}
}
-(void)setInputLayer {
for (int i=0; i<100; i++) {
Neuron *neuron = self.arrayOfLayers[0][i];
NSNumber *output = self.learningArray[i];
neuron.output = output.doubleValue;
}
}
#pragma mark - Algorythm
-(void)learn {
double currentAnswer;
NSMutableArray *shuffledData = [self.learningData mutableCopy];
[self shuffleArray:shuffledData];
[self setRandomWeights];
int countOfLearningArray = (int) (0.7*[self.learningData count]);
for (int k=0; k<countOfLearningArray; k++) {
[self.epocheLearningArrays addObject:[shuffledData objectAtIndex:k]];
}
for (int k=countOfLearningArray; k<[shuffledData count]; k++) {
[self.epocheTestingArrays addObject:[shuffledData objectAtIndex:k]];
}
NSNumber *learningPropagation=#(-100);
NSNumber *testPropagation=#(100);
NSInteger epocheCount=0;
while (fabs(learningPropagation.doubleValue-testPropagation.doubleValue)>0.001 && epocheCount<kMaxEpocheCount) {
learningPropagation = #0;
for (NSArray *learningArray in self.epocheLearningArrays) {
self.learningArray = [learningArray mutableCopy];
NSNumber *lastObject = [learningArray lastObject];
currentAnswer = lastObject.doubleValue;
[self.learningArray removeLastObject];
self.answer = currentAnswer;
[self setInputLayer];
[self forwardPass];
[self calculatePropagation:self.arrayOfLayers[2][0]];
if (fabs(self.output-self.answer)>0.0001) {
[self backPass];
[self resetWeights];
}
learningPropagation = #(learningPropagation.doubleValue + self.propagation);
}
learningPropagation = #(learningPropagation.doubleValue/[self.epocheLearningArrays count]);
testPropagation = #0;
for (NSArray *testArray in self.epocheTestingArrays) {
self.learningArray = [testArray mutableCopy];
NSNumber *lastObject = [testArray lastObject];
currentAnswer = lastObject.doubleValue;
[self.learningArray removeLastObject];
self.answer = currentAnswer;
[self setInputLayer];
[self forwardPass];
[self calculatePropagation:self.arrayOfLayers[2][0]];
testPropagation = #(testPropagation.doubleValue + self.propagation);
}
testPropagation = #(testPropagation.doubleValue/[self.epocheTestingArrays count]);
epocheCount++;
}
}
-(void)calculatePropagation:(Neuron *)neuron
{
self.propagation= 0.5*pow((neuron.output - self.answer), 2);
}
#define alpha 0.5
-(void)forwardPass
{
for (int i=0; i<[self.arrayOfLayers count]-1; i++) {
for (int j=0; j<[self.arrayOfLayers[i+1] count]; j++) {
double sum=0;
for (int z=0; z<[self.arrayOfLayers[i] count]; z++) {
Neuron *neuron = (Neuron *)self.arrayOfLayers[i][z];
sum+=[(NSNumber *)neuron.weights[j] doubleValue]*neuron.output;
}
Neuron *neuron = (Neuron *)self.arrayOfLayers[i+1][j];
neuron.output = tanh(alpha*sum);
}
}
Neuron *outputNeuron = self.arrayOfLayers[2][0];
self.output = outputNeuron.output;
}
-(void)backPass
{
for (NSInteger i=[self.arrayOfLayers count]-1; i>=0; i--) {
for (int j=0; j<[self.arrayOfLayers[i] count]; j++) {
double temp=0;
if (i==[self.arrayOfLayers count]-1) {
Neuron *neuron = (Neuron *)self.arrayOfLayers[i][j];
temp = neuron.output-self.answer;
neuron.propagation = temp;
} else {
for (int z=0; z<[self.arrayOfLayers[i+1] count]; z++) {
Neuron *neuron1 = (Neuron *)self.arrayOfLayers[i+1][z];
Neuron *neuron2 = (Neuron *)self.arrayOfLayers[i][j];
temp = neuron1.propagation * [(NSNumber *)neuron2.weights[z] doubleValue];
}
Neuron *neuron = (Neuron *)self.arrayOfLayers[i][j];
neuron.propagation = temp;
}
}
}
}
#define gamma 0.01
-(void)resetWeights
{
for (int i=0; i<[self.arrayOfLayers count]-1; i++) {
for (int j=0; j<[self.arrayOfLayers[i] count]; j++) {
Neuron *neuron = (Neuron *)self.arrayOfLayers[i][j];
for (int z=0; z<[self.arrayOfLayers[i+1] count]; z++) {
neuron.weights[z] = #([(NSNumber *)neuron.weights[z] doubleValue]- gamma * neuron.propagation * neuron.output);
}
}
}
}
-(void)shuffleArray:(NSMutableArray *)array {
NSUInteger count = [array count];
for (NSUInteger i = 0; i < count; ++i) {
NSInteger remainingCount = count - i;
NSInteger exchangeIndex = i + arc4random_uniform((u_int32_t )remainingCount);
[array exchangeObjectAtIndex:i withObjectAtIndex:exchangeIndex];
}
}
The error was in method resetWeights. The solution:
-(void)resetWeights
{
for (int i=0; i<[self.arrayOfLayers count]-1; i++) {
for (int j=0; j<[self.arrayOfLayers[i] count]; j++) {
Neuron *neuron = (Neuron *)self.arrayOfLayers[i][j];
for (int z=0; z<[self.arrayOfLayers[i+1] count]; z++) {
Neuron *nextLayerNeuron = (Neuron *)self.arrayOfLayers[i+1][z];
neuron.weights[z] = #([(NSNumber *)neuron.weights[z] doubleValue]- gamma * nextLayerNeuron.propagation * neuron.output);
}
}
}
}
My question is simple, I have the following code, it creates an array of Hues got from a function that returns the UIColor of an image (this is not important, just context). So, I need to create this array as fast as possible, this test runs with only a 5x5 pixels image and it takes about 3sec, I want to be able to run a 50x50 pixels image (at least) in about 2 secods (tops), any ideas?
- (void)createArrayOfHues: (UIImage *)imageScaned{
if (imageScaned != nil) {
NSLog(#"Creating Array...");
UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];
img.contentMode = UIViewContentModeScaleToFill;
img.image = imageScaned;
img.contentMode = UIViewContentModeRedraw;
img.hidden = YES;
int i = 0;
CGFloat hue = 0;
CGFloat sat = 0;
CGFloat brit = 0;
CGFloat alph = 0;
CGFloat hue2 = 0;
CGFloat sat2 = 0;
CGFloat brit2 = 0;
CGFloat alph2 = 0;
[_colorsArray removeAllObjects];
[_satForHue removeAllObjects];
[_britForHue removeAllObjects];
[_alphForHue removeAllObjects];
_colorsArray = [[NSMutableArray alloc] initWithCapacity:(25)];
_satForHue = [[NSMutableArray alloc] initWithCapacity:(25)];
_britForHue = [[NSMutableArray alloc] initWithCapacity:(25)];
_alphForHue = [[NSMutableArray alloc] initWithCapacity:(25)];
while (i<25) {
for (int y=1; y <= 5; y++){
for (int x = 1; x <= 2.5; x++){
if (x != (5-x)){
UIColor *color = [self colorMatch:imageScaned :x :y];
UIColor *color2 = [self colorMatch:imageScaned :(5-x) :y];
if([color getHue:&hue saturation:&sat brightness:&brit alpha:&alph] && [color2 getHue:&hue2 saturation:&sat2 brightness:&brit2 alpha:&alph2]){
NSNumber *hueId = [NSNumber numberWithFloat:(float)hue];
NSNumber *satId = [NSNumber numberWithFloat:(float)sat];
NSNumber *britId = [NSNumber numberWithFloat:(float)brit];
NSNumber *alphId = [NSNumber numberWithFloat:(float)alph];
NSNumber *hueId2 = [NSNumber numberWithFloat:(float)hue2];
NSNumber *satId2 = [NSNumber numberWithFloat:(float)sat2];
NSNumber *britId2 = [NSNumber numberWithFloat:(float)brit2];
NSNumber *alphId2 = [NSNumber numberWithFloat:(float)alph2];
[_colorsArray insertObject:hueId atIndex:i];
[_satForHue insertObject:satId atIndex:i];
[_britForHue insertObject:britId atIndex:i];
[_alphForHue insertObject:alphId atIndex:i];
[_colorsArray insertObject:hueId2 atIndex:(i+1)];
[_satForHue insertObject:satId2 atIndex:(i+1)];
[_britForHue insertObject:britId2 atIndex:(i+1)];
[_alphForHue insertObject:alphId2 atIndex:(i+1)];
}
NSLog(#"color inserted at %i with x: %i and y: %i" , i , x, y);
i++;
}else {
UIColor *color = [self colorMatch:imageScaned :x :y];
if([color getHue:&hue saturation:&sat brightness:&brit alpha:&alph]){
NSNumber *hueId = [NSNumber numberWithFloat:(float)hue];
NSNumber *satId = [NSNumber numberWithFloat:(float)sat];
NSNumber *britId = [NSNumber numberWithFloat:(float)brit];
NSNumber *alphId = [NSNumber numberWithFloat:(float)alph];
[_colorsArray insertObject:hueId atIndex:i];
[_satForHue insertObject:satId atIndex:i];
[_britForHue insertObject:britId atIndex:i];
[_alphForHue insertObject:alphId atIndex:i];
}
}
}
}
}
NSLog(#"Returns the array");
}else{
NSLog(#"Returns nothing");
}
}
The code for colorMatch:
- (UIColor *) colorMatch: (UIImage *)image :(int) x :(int) y {
isBlackColored = NO;
if (image == nil){
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL customColor = [defaults boolForKey:#"custom_color"];
if (customColor){
float red = [defaults floatForKey:#"custom_color_slider_red"];
float green = [defaults floatForKey:#"custom_color_slider_green"];
float blue = [defaults floatForKey:#"custom_color_slider_blue"];
return [UIColor colorWithRed:red green:green blue:blue alpha:1];
}else
isDefaultS = YES;
}
else{
CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
const UInt8* data = CFDataGetBytePtr(pixelData);
int pixelInfo = ((image.size.width * y) + x ) * 4;
UInt8 red = data[pixelInfo];
UInt8 green = data[(pixelInfo + 1)];
UInt8 blue = data[pixelInfo + 2];
UInt8 alpha = data[pixelInfo + 3];
CFRelease(pixelData);
float redC = red/255.0f;
float greenC = green/255.0f;
float blueC = blue/255.0f;
UIColor* color = [UIColor colorWithRed:redC green:greenC blue:blueC alpha:alpha/255.0f];
return color;
}
return nil;
}
I think your main performance bottleneck is not the initialization of NSMutableArray instances, but the way you index your image:
UIColor *color = [self colorMatch:imageScaned :x :y];
I guess this method converts the UIImage to a CGImageRef, copies its data, indexes it, then destroys/releases these temporary objects, or something like this - for every single pixel...
You should refactor this code to get hold of the image buffer only once, and then work with it like a regular C pointer/array. If that doesn't solve your performance problem, you should do some profiling.
So I'm making a biginteger program, and I'm having a problem with adding two arrays that aren't the same length. The problem I'm having is with the add method. If I'm iterating through an array is there any way to test if element is out of bounds. I've tried testing if the element in a is equal to nil, but I still get the exception. Any help would be great thanks.
#import <Foundation/Foundation.h>
#import "MPInteger.h"
#implementation MPInteger
{
}
-(id) initWithString: (NSString *) x
{
self = [super init];
if (self) {
intString = [NSMutableArray array];
for (int i = 0; i < [x length]; i++) {
NSString *ch = [x substringWithRange:NSMakeRange(i, 1)];
[intString addObject:ch];
}
}
return self;
}
-(NSString *) description
{
return self.description;
}
- (MPInteger *) add: (MPInteger *) x {
NSMutableArray *a = self->intString;
NSMutableArray *b = x->intString;
NSMutableArray *c = [NSMutableArray array];
NSInteger arrayCount;
if (a < b) {
arrayCount = [b count];
} else {
arrayCount = [a count];
}
int num = 10;
int carry = 1;
NSNumber *total;
NSNumber *carrySum;
for (int i = 0; i < arrayCount; i++) {
if (a[i] == nil) {
total = #([b[i] intValue]);
[c addObject:total];
} else if (b[i] == nil) {
total = #([a[i] intValue]);
[c addObject:total];
} else {
total = #([a[i] intValue] + [b[i] intValue]);
[c addObject:total];
}
}
for (NSInteger j = [c count]-1; j >=0; j--) {
if ([c[j] intValue] >= num) {
total = #([c[j] intValue] - num);
carrySum = #([c[j-1] intValue] + carry);
[c replaceObjectAtIndex:j withObject:total];
[c replaceObjectAtIndex:j-1 withObject: carrySum];
}
}
NSString *str = [c componentsJoinedByString:#""];
NSLog(#"%#", str);
return x;
}
-(MPInteger *) multiply: (MPInteger *) x
{
NSMutableArray *a = self->intString;
NSMutableArray *b = x->intString;
NSMutableArray *c = [NSMutableArray array];
NSMutableArray *sum = [NSMutableArray array];
NSNumber *total;
NSNumber *carrySum;
int num = 10;
NSNumber *endZero = 0;
NSInteger bottomCount = [b count]-1;
while (bottomCount != -1) {
for (int i = 0; i < [a count]; i++) {
total = #([a[i] intValue] * [[b objectAtIndex:bottomCount] intValue]);
if (bottomCount == [b count] -1) {
[c addObject:total];
} else {
[c replaceObjectAtIndex:i withObject:total];
}
}
for (NSInteger j = [c count]-1; j>=0; j--) {
NSString *carry = [NSString stringWithFormat:#"%d", [c[j] intValue]];
NSString *carry2 = [carry substringToIndex:1];
int carryFinal = [carry2 intValue];
NSString *carry3 = [carry2 stringByAppendingString:#"0"];
int carry4 = [carry3 intValue];
if ([c[j] intValue] >= num) {
total = #([c[j] intValue] - carry4);
carrySum = #([c[j-1] intValue] + carryFinal);
[c replaceObjectAtIndex:j withObject:total];
[c replaceObjectAtIndex:j-1 withObject: carrySum];
} else {
if(j == 0) {
if (bottomCount == [b count] -1) {
bottomCount = bottomCount - 1;
NSString *str = [c componentsJoinedByString:#""];
[sum addObject: str];
} else {
[c addObject:#([endZero intValue])];
bottomCount = bottomCount - 1;
NSString *str = [c componentsJoinedByString:#""];
[sum addObject: str];
}
}
}
}
}
NSMutableArray *finalSum = [NSMutableArray array];
MPInteger *ele1;
MPInteger *ele2;
MPInteger *eleSum;
NSNumber *endZ= #(0);
[finalSum insertObject:endZ atIndex:0];
for (int k = 0; k < [sum count]; k++) {
NSString *str= [NSString stringWithFormat:#"%d", [sum[k] intValue]];
NSString *str2 = [NSString stringWithFormat:#"%d", [sum[k+1] intValue]];
ele1 = [[MPInteger alloc] initWithString:str];
ele2 = [[MPInteger alloc] initWithString:str2];
eleSum = [ele1 add: ele2];
NSLog(#"%#", eleSum);
}
NSLog(#"%#", sum);
return self;
}
Updated this
for (int i = 0; i < arrayCount; i++) {
if (a[i] == nil) {
total = #([b[i] intValue]);
[c addObject:total];
} else if (b[i] == nil) {
total = #([a[i] intValue]);
[c addObject:total];
} else {
total = #([a[i] intValue] + [b[i] intValue]);
[c addObject:total];
}
}
has now become:
NSMutableArray *c = a.count > b.count ? [a mutableCopy] : [b mutableCopy];
NSArray *shortestArray = a.count > b.count ? b : a;
[shortestArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSNumber *currentNumber, NSUInteger idx, BOOL *stop) {
c[idx] = #(currentNumber.integerValue + [c[idx] integerValue]);
NSLog(#"%#", c[idx]);
}];
What I think I need to do is every index that is in array a and not b or vise versa, is add beginning zeros, but I don't know how to do that.
I printed out what it does after each iteration and it gives:
2013-09-02 12:31:42.630 Asgn1[42471:303] 5
2013-09-02 12:31:42.632 Asgn1[42471:303] 3
2013-09-02 12:31:42.632 Asgn1[42471:303] 1
And a final answer of:
2013-09-02 12:31:42.633 Asgn1[42471:303] 353
For the code that is failing would it not be simpler to take a mutableCopy of the large array and then loop over the smaller array for the calculations?
Perhaps something like this:
NSMutableArray *c = a.count > b.count ? [a mutableCopy] : [b mutableCopy];
NSArray *shortestArray = a.count > b.count ? b : a;
[shortestArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSNumber *currentNumber, NSUInteger idx, BOOL *stop) {
c[idx] = #(currentNumber.integerValue + [c[idx] integerValue]);
}];
I have a problem with counting my module. I am doing the following.
- (void)makeGrid:withData:(NSDictionary * )data
{
NSLog(#"aantal is: %d",[data count]);
int xStart = 0;
int yStart = 0;
int xCurrent = xStart;
int yCurrent = yStart;
int xStepSize = 165;
int yStepSize = 251;
int xCnt = 3 ;
int yCnt = [data count] % 3;
int cellCounter = 0;
UIView * gridContainerView = [[UIView alloc] init];
[keeperView addSubview:gridContainerView];
for (int y = 0; y < yCnt; y++) {
for (int x = 0; x < xCnt; x++) {
printf("xCurrent %d yCurrent %d \n", xCurrent, yCurrent);
NSString *url1 = #"player_imgUrl";
NSString *url2 = [NSString stringWithFormat:#"%i", x];
NSString *url3 = [url1 stringByAppendingString:url2];
NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[data objectForKey:url3]]];
UIImage* myImage = [[UIImage alloc] initWithData:imageData];
UIImageView * myView = [[UIImageView alloc] initWithImage:myImage];
CGRect rect = myView.frame;
rect.origin.x = xCurrent;
rect.origin.y = yCurrent;
myView.frame = rect;
myView.tag = cellCounter;
[gridContainerView addSubview:myView];
//just label stuff
UILabel * myLabel = [[UILabel alloc] init];
[gridContainerView addSubview:myLabel];
//--------------------------------
xCurrent += xStepSize;
cellCounter++;
}
xCurrent = xStart;
yCurrent += yStepSize;
}
CGRect repositionRect = gridContainerView.frame;
repositionRect.origin.y = 100;
gridContainerView.frame = repositionRect;
}
My NSLog says that in my data object are 16 values. And when I run it, it only shows 3 imageviews. Does anybody know what I am doing wrong?
Please help,
Kind regads.
After reading your code, the number of imageviews should be (xCnt * yCnt).
Your problem is here:
int yCnt = [data count] % 3;
the yCnt is 1 when your data is 16, that's why your result is 3 imageviews only.
to overcome this issue, you should do the following:
yCnt = (data.count / xCnt) + 1;
for (int y = 0 ; y < yCnt; y++)
{
for (int x = 0; x < xCnt; x++)
{
if ((y == (yCnt - 1)) && (x > (data.count % xCnt)))
{
break;
}
else {
// Your Grid code here
}
}
}
Hope This helps.
int yCnt = [data count] % 3;
gives 1 when [data count] == 16;
How do I convert binary data to hex value in obj-c?
Example:
1111 = F,
1110 = E,
0001 = 1,
0011 = 3.
I have a NSString of 10010101010011110110110011010111, and i want to convert it to hex value.
Currently I'm doing in a manual way. Which is,
-(NSString*)convertToHex:(NSString*)hexString
{
NSMutableString *convertingString = [[NSMutableString alloc] init];
for (int x = 0; x < ([hexString length]/4); x++) {
int a = 0;
int b = 0;
int c = 0;
int d = 0;
NSString *A = [NSString stringWithFormat:#"%c", [hexString characterAtIndex:(x)]];
NSString *B = [NSString stringWithFormat:#"%c", [hexString characterAtIndex:(x*4+1)]];
NSString *C = [NSString stringWithFormat:#"%c", [hexString characterAtIndex:(x*4+2)]];
NSString *D = [NSString stringWithFormat:#"%c", [hexString characterAtIndex:(x*4+3)]];
if ([A isEqualToString:#"1"]) { a = 8;}
if ([B isEqualToString:#"1"]) { b = 4;}
if ([C isEqualToString:#"1"]) { c = 2;}
if ([D isEqualToString:#"1"]) { d = 1;}
int total = a + b + c + d;
if (total < 10) { [convertingString appendFormat:#"%i",total]; }
else if (total == 10) { [convertingString appendString:#"A"]; }
else if (total == 11) { [convertingString appendString:#"B"]; }
else if (total == 12) { [convertingString appendString:#"C"]; }
else if (total == 13) { [convertingString appendString:#"D"]; }
else if (total == 14) { [convertingString appendString:#"E"]; }
else if (total == 15) { [convertingString appendString:#"F"]; }
}
NSString *convertedHexString = convertingString;
return [convertedHexString autorelease];
[convertingString release];
}
Anyone have better suggestion? This is taking too long.
Thanks in advance.
I have never been much of a C hacker myself, but a problem like this is perfect for C, so here is my modest proposal - coded as test code to run on the Mac, but you should be able to copy the relevant bits out to use under iOS:
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init];
NSString *str = #"10010101010011110110110011010111";
char* cstr = [str cStringUsingEncoding: NSASCIIStringEncoding];
NSUInteger len = strlen(cstr);
char* lastChar = cstr + len - 1;
NSUInteger curVal = 1;
NSUInteger result = 0;
while (lastChar >= cstr) {
if (*lastChar == '1')
{
result += curVal;
}
/*
else
{
// Optionally add checks for correct characters here
}
*/
lastChar--;
curVal <<= 1;
}
NSString *resultStr = [NSString stringWithFormat: #"%x", result];
NSLog(#"Result: %#", resultStr);
[p release];
}
It seems to work, but I am sure that there is still room for improvement.
#interface bin2hex : NSObject
+(NSString *)convertBin:(NSString *)bin;
#end
#implementation bin2hex
+(NSString*)convertBin:(NSString *)bin
{
if ([bin length] > 16) {
NSMutableArray *bins = [NSMutableArray array];
for (int i = 0;i < [bin length]; i += 16) {
[bins addObject:[bin substringWithRange:NSMakeRange(i, 16)]];
}
NSMutableString *ret = [NSMutableString string];
for (NSString *abin in bins) {
[ret appendString:[bin2hex convertBin:abin]];
}
return ret;
} else {
int value = 0;
for (int i = 0; i < [bin length]; i++) {
value += pow(2,i)*[[bin substringWithRange:NSMakeRange([bin length]-1-i, 1)] intValue];
}
return [NSString stringWithFormat:#"%X", value];
}
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
// insert code here...
NSLog(#"0x%#",[bin2hex convertBin:#"10010101010011110110110011010111"]);
}
return 0;
}
I get the result of 0x954F6CD7 for 10010101010011110110110011010111 and it seems to be instant
Maybe easiest would be to setup a NSDictionary for quick lookups?
[NSDictionary dictionaryWithObjects...]
since it is a limited number of entries.
"0000" -> 0
...
"1111" -> F