convert c++ vector to Objective-c - c++

I currently have
vector<vector<cv::Point>> example;
and want to be able to pass it to a swift function, So I assume I should start by making it like this (or is there easier way?):
NSArray[NSArray[Int,Int]]
cv::Point is an object of two int properties.
I have tried
NSMutableArray *example1[example.size()];
for(i = 0;i< example.size();i++){
if(example[i].size() > 5){ //irrelevant
NSMutableArray *second[example[i].size()];
for(int p = 0;p<example[i].size();p++){
NSInteger p1 = example[i][p].x;
NSInteger p2 = example[i][p].y;
NSInteger point[2] = {p1,p2};
[second addObject: point];
}
[example addObject: second];
}
}
I have been spending ages and constantly getting different data type errors, etc. How would you do it, or correct this?
Thanks

You can use NSValue to store a simple struct into NSMutableArray:
NSMutableArray *example1 = [NSMutableArray arrayWithCapacity:example.size()];
for(int i = 0;i< example.size();i++){
if(example[i].size() > 5){ //irrelevant
NSMutableArray *second = [NSMutableArray arrayWithCapacity:example[i].size()];
for(int p = 0;p<example[i].size();p++){
NSValue *point = [[NSValue alloc] initWithBytes:&example[i][p] objCType:#encode(cv::Point)];
[second addObject:point];
}
[example1 addObject:second];
}
}

Related

how to I change CCArray type to SpriteFrame?

The error lies in
CCAnimation *_runAnim = CCAnimation::createWithSpriteFrames(zoewalkingFrames, 0.1);
this line, when I'm trying to pass CCArray zoewalkingFrames to CCAnimation _runAnim, the log says "Reference to type 'const Vector could not bind to an lvalue of type 'CCArray' aka '"here, so what should I do so I can pass the CCArray var to SpriteFrame? Thanks
#include "ZoeAnime.h"
using namespace cocos2d;
bool ZoeAnime::init()
{
if ( !Node::init() )
{
return false;
}
auto spritecache = SpriteFrameCache::getInstance();
spritecache->addSpriteFramesWithFile("zoeanime.plist");
CCSpriteBatchNode *_spritesheet = CCSpriteBatchNode::create("zoeanime.png");
this->addChild(_spritesheet);
CCArray* zoewalkingFrames = CCArray::create();
for(int i = 1; i <= 3; i++) {
CCString* filename = CCString::createWithFormat("zoewalking%0d.png", i);
CCSpriteFrame* frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(filename->getCString());
zoewalkingFrames->addObject(frame);
}
CCAnimation *_runAnim = CCAnimation::createWithSpriteFrames(zoewalkingFrames, 0.1);
CCSprite* zoe = CCSprite::createWithSpriteFrameName("zoewalking01.png");
CCSize winsize = CCDirector::sharedDirector()->getWinSize();
zoe->setPosition(ccp(winsize.width*0.5, winsize.height*0.5));
CCAction* action = CCRepeatForever::create(CCAnimate::create(_runAnim));
zoe->runAction(action);
_spritesheet->addChild(zoe);
return true;
}
This is a good one for reference, just replace CCArray with Vector data type.
http://discuss.cocos2d-x.org/t/erro-sprite-createwithspriteframes/16887

How do we enumerate and modify positions array of CCsprite inside Update method?

How do we enumerate and alter our object's position (contained in array) for each delta time?
I put some CCsprite objects inside array, then I displayed them in scene, but also I wanted to make them move with modifying update method, I failed on last part.
How do I get around this ?
#implementation GameScene
{
Hunter *_hunter;
Bird *_bird;
NSMutableArray *_arrayOfBirds;
}
-(void)update:(CCTime)delta{
CGSize viewSize = [CCDirector sharedDirector].viewSize;
float birdSpeed = 50;
for (Bird *birds in _arrayOfBirds) {
if (birds.position.x < 0) {
birds.flipX = YES;
}
if (birds.position.x > viewSize.width) {
birds.flipX = NO;
}
float distanceToMove = birdSpeed * delta;
float direction = birds.flipX ? 1 : -1;
float newX = birds.position.x + direction * distanceToMove;
float newY = birds.position.y;
birds.position = ccp(newX, newY);
}
}
-(void)addBird{
CGSize viewSize = [CCDirector sharedDirector].viewSize;
for (int i=0; i < 4; i++) {
_bird = [[Bird alloc]initWithBirdType:(i)];
_bird.position = ccp(viewSize.width * 0.5f + 30 * i , viewSize.height * 0.9f - 15* i);
[self addChild:_bird];
[_arrayOfBirds addObject:_bird];
}
}
You forgot to initialize your array
here (assuming ARC)
-(id) init {
if(self=[super init]) {
_arrayOfBirds = [[NSMutableArray alloc] init];
// the rest
}
return self;
}

error index beyond bounds

-(id) init
{
if( (self=[super init])) {
_targets = [[NSMutableArray alloc] init];
temp = [NSArray arrayWithObjects:#"1", #"2", #"3", #"4",nil];
tempArray = [[NSMutableArray alloc] initWithArray:temp];
resultArray = [[NSMutableArray alloc] init];
[self thelogic];
}
return self;
}
-(void)thelogic
{
int i;
int count = 4;
for (i = 0; i < 3; i ++) {
int index = arc4random() % (count - i);
[resultArray addObject:[tempArray objectAtIndex:index]];
CCSprite *target = [CCSprite spriteWithFile:[NSString stringWithFormat:#"%#.png", [tempArray objectAtIndex:index]]];
target.tag = [[NSString stringWithFormat:#"%#",[tempArray objectAtIndex:index]] integerValue];
[self addChild:target];
[_targets addObject:target];
[tempArray removeObjectAtIndex:index];
}
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[_targets removeAllObjects];
[self thelogic];
}
from the up code, I get three different numbers and they make three sprites with different image when enter this scene, and I want to touch the screen, the three old sprites will be removed, and three new sprites will show, but the up code always crashes, so how should I fix it? thanks
It is hard to understand what you are trying to do in your theLogic method, but I would suggest you to replace
int index = arc4random() % (count - i);
with
int index = arc4random() % [tempArray count];
This will fix the crash, but I doubt that your program will work as expected. Indeed, you only populate tempArray in the init method; the first call to theLogic will remove all of its elements, and as far as I see the array is not populated anymore. So, when you make ccTouchesBegan be called and then theLogic, tempArray will be empty.
Sorry if I am missing any points.

Combining two c++ files in Xcode for OpenCV (Use of undeclared identifier CVSquares)

I am trying to merge OpenCVCircles and OpenCVSquares for a project. If I open them directly from the Xcode project files (independently) they work fine, but if I move the CVSquares.h and CVSquares.cpp files to the OpenCVCircles project, it starts complaining: "Use of undeclared identifier CVSquares". This happens in CVWrapper.mm (see problematic line towards the end):
#import "CVWrapper.h"
#import "CVCircles.h"
#import "CVSquares.h"
#import "UIImage+OpenCV.h"
//remove 'magic numbers' from original C++ source so we can manipulate them from obj-C
#define TOLERANCE 0.3
#define THRESHOLD 50
#define LEVELS 9
#define ACCURACY 0
#implementation CVWrapper
+ (NSMutableArray*) detectedCirclesInImage:(UIImage*) image
{
double dp = 1;
double minDist = 10;
double param1 = 100;
double param2 = 30;
int min_radius = 1;
int max_radius = 30;
return [[self class] detectedCirclesInImage:image
dp:dp
minDist:minDist
param1:param1
param2:param2
min_radius:min_radius
max_radius:max_radius];
}
+ (NSMutableArray*) detectedCirclesInImage:(UIImage*)image
dp:(CGFloat)dp
minDist:(CGFloat)minDist
param2:(CGFloat)param2
{
double param1 = 100;
int min_radius = 1;
int max_radius = 30;
return [[self class] detectedCirclesInImage:image
dp:dp
minDist:minDist
param1:param1
param2:param2
min_radius:min_radius
max_radius:max_radius];
}
+ (NSMutableArray*) detectedCirclesInImage:(UIImage*)image
dp:(CGFloat)dp
minDist:(CGFloat)minDist
param2:(CGFloat)param2
min_radius:(int)min_radius
max_radius:(int)max_radius
{
double param1 = 100;
return [[self class] detectedCirclesInImage:image
dp:dp
minDist:minDist
param1:param1
param2:param2
min_radius:min_radius
max_radius:max_radius];
}
+ (NSMutableArray*) detectedCirclesInImage:(UIImage*)image
dp:(CGFloat)dp
minDist:(CGFloat)minDist
param1:(CGFloat)param1
param2:(CGFloat)param2
min_radius:(int)min_radius
max_radius:(int)max_radius
{
NSMutableArray *array = [[NSMutableArray alloc] init];
UIImage* modifiedImage = nil;
cv::Mat matImage = [image CVMat];
int num_circles = 0;
matImage = CVCircles::detectedCirclesInImage
(matImage, dp, minDist, param1, param2, min_radius, max_radius, &num_circles);
modifiedImage = [UIImage imageWithCVMat:matImage];
NSLog(#"n circles: %i",num_circles);
[array addObject:modifiedImage];
[array addObject:[NSNumber numberWithInt:num_circles]];
NSLog(#"array: %#, %#",[array objectAtIndex:0],[array objectAtIndex:1]);
return array;
}
+ (UIImage*) detectedSquaresInImage:(UIImage*) image
{
//if we call this method with no parameters,
//we use the defaults from the original c++ project
return [[self class] detectedSquaresInImage:image
tolerance:TOLERANCE
threshold:THRESHOLD
levels:LEVELS
accuracy:ACCURACY];
}
+ (UIImage*) detectedSquaresInImage:(UIImage*) image
tolerance:(CGFloat) tolerance
threshold:(NSInteger)threshold
levels:(NSInteger)levels
accuracy:(NSInteger)accuracy
{
//NSLog (#"detectedSquaresInImage");
UIImage* result = nil;
cv::Mat matImage = [image CVMat];
//ERROR IS ON THIS LINE
matImage = CVSquares::detectedSquaresInImage (matImage, tolerance, threshold, levels, accuracy);
result = [UIImage imageWithCVMat:matImage];
//NSLog (#"detectedSquaresInImage result");
return result;
}
#end
I have the impression that I'm double defining something, missing .mm in some files, or the like but I have been struggling with this for the whole day and I can't make it work (today was my first time with C++). Any help would be much appreciated.
PS: Thanks to foundry (whoever he/she is) for the 2 awesome plug & play projects!
Ended up pasting all the CVSquares.cpp code into the CVCircles.cpp code (as well as the CVSquares.h into the CVCircles.h) and calling:
matImage = CVCircles::detectedSquaresInImage (matImage, tolerance, threshold, levels, accuracy);
Couldn't get it to work otherwise. Hope it helps!

warnings when using setDelay and addFrameWithFilename

I want to use the following lines of code in my project.
// Create the intro image
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCSprite *introImage = [CCSprite spriteWithFile:#"intro1.png"];
[introImage setPosition:ccp(screenSize.width/2, screenSize.height/2)];
[self addChild:introImage];
// Create the intro animation, and load it from intro1 to intro7.png
CCAnimation *introAnimation = [CCAnimation animation];
[introAnimation setDelay:2.5f];
for (int frameNumber=0; frameNumber < 8; frameNumber++) {
CCLOG(#"Adding image intro%d.png to the introAnimation.",frameNumber);
[introAnimation addFrameWithFilename:
[NSString stringWithFormat:#"intro%d.png",frameNumber]];
I get the warning:
instance method '-setDelay:' not found (return type defaults to 'id')
pointing to the line
[introAnimation setDelay:2.5f];
and a similar warning pointing to the line
[introAnimation addFrameWithFilename: [NSString stringWithFormat:#"intro%d.png",frameNumber]];
Has setDelay and addFrameWithFilename been deprecated? If yes, what should I use in their place. Please help.
hmmm ... not certain these methods exist at all. Here is an example from my code base (cocos2 version 2.0).
+ (CCAnimation *) getAnimationForSoldier:(Soldier *)theSoldier animationType:(mapAnimationTypeE)animationType {
id animation = nil;
NSString *animationName = [SpriteUtils getAnimationNameForSoldier:theSoldier animationType:animationType];
if (!animationName) return nil;
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:[NSString stringWithFormat:#"%#.plist", animationName]];
if ((animation = [[CCAnimationCache sharedAnimationCache] animationByName:animationName])) {
return animation;
} else {
NSUInteger numberOfFrames = 8;
if (animationType == mapAnimationTypeCast || animationType == mapAnimationTypeSkill) numberOfFrames = 20;
NSMutableArray *frames = [NSMutableArray arrayWithCapacity:numberOfFrames];
for (NSUInteger i = 1 ; i <= numberOfFrames ; i++) {
NSString *frName = [SpriteUtils getFrameNameForAnimationNamed:animationName andFrame:i];
CCSpriteFrame *frr = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:frName];
if (frr) {
[frames addObject:frr];
} else {
MPLOGERROR(#"*** No frame named [%#], bailing out.", frName);
return nil;
}
[frames addObject:frr];
}
animation = [CCAnimation animationWithSpriteFrames:frames delay:.06];
[[CCAnimationCache sharedAnimationCache] addAnimation:animation name:animationName];
}
return animation;
}
note : first create your spriteframes array, then create the animation with the array and the desired delay.
The delay is delay between each frame (not the total duration).
If you are using cocos2d version 2.N, the setter for delay is
animation.delayPerUnit = 0.6f;