Multiple CGPoints to CGRect - iphone

I have a a set of CGPoints which represent a shape which is a bit like an upside down 'T' shape, now I want to convert those points into a CGRect which fits inside the shape, so to create a CGRect which encompasses the entire shape I just loop through and work out the lowest x and y for the top left and the highest x and y for the bottom right which is great but leaves white areas outside of the image, how could I figure out the largest rectangle without white areas so the final shape is more like an '|' shape? My code so far:
CGPoint topLeft = CGPointZero;
CGPoint bottomRight = CGPointZero;
for( NSValue *value in points ) {
CGPoint point = [value CGPointValue];
if( topLeft.x == 0 || topLeft.x > point.x ) shapeRect.x = point.x;
if( topLeft.y == 0 || topLeft.y > point.y ) shapeRect.y = point.y;
if( bottomRight.x < point.x ) bottomRight.x = point.x;
if( bottomRight.y < point.y ) bottomRight.y = point.y;
}
CGRect shapeRect = CGRectMake(topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y);
EDIT: I've drawn some pics to show what I'm trying to achieve. Grey areas show the CGRect.
Here's the image shape, I have coordinates for each point in the shape:
Image Hosted by ImageShack.us http://img684.imageshack.us/img684/121/crop1.png
Here's what my code above produces:
Image Hosted by ImageShack.us http://img26.imageshack.us/img26/2521/crop2j.png
Here's what I'm trying to achieve:
Image Hosted by ImageShack.us http://img689.imageshack.us/img689/5499/crop3.png

Hard to get a grip on what you are actually asking about. In regards to the title this function will create the smallest rect for any number of CGPoints.
CGRect CGRectSmallestWithCGPoints(CGPoint pointsArray[], int numberOfPoints)
{
CGFloat greatestXValue = pointsArray[0].x;
CGFloat greatestYValue = pointsArray[0].y;
CGFloat smallestXValue = pointsArray[0].x;
CGFloat smallestYValue = pointsArray[0].y;
for(int i = 1; i < numberOfPoints; i++)
{
CGPoint point = pointsArray[i];
greatestXValue = MAX(greatestXValue, point.x);
greatestYValue = MAX(greatestYValue, point.y);
smallestXValue = MIN(smallestXValue, point.x);
smallestYValue = MIN(smallestYValue, point.y);
}
CGRect rect;
rect.origin = CGPointMake(smallestXValue, smallestYValue);
rect.size.width = greatestXValue - smallestXValue;
rect.size.height = greatestYValue - smallestYValue;
return rect;
}
Can be used like this
CGPoint poinstArray[] = {topLeft, bottomRight};
CGRect smallestRect = CGRectSmallestWithCGPoints(poinstArray, 2);

Swift version of hfossli (it works great !) :
func pointToRect(pointsArray: [CGPoint]) -> CGRect {
var greatestXValue = pointsArray[0].x
var greatestYValue = pointsArray[0].y
var smallestXValue = pointsArray[0].x
var smallestYValue = pointsArray[0].y
for point in pointsArray {
greatestXValue = max(greatestXValue, point.x);
greatestYValue = max(greatestYValue, point.y);
smallestXValue = min(smallestXValue, point.x);
smallestYValue = min(smallestYValue, point.y);
}
let origin = CGPoint(x: smallestXValue, y: smallestYValue)
let size = CGSize(width: greatestXValue - smallestXValue, height: greatestYValue - smallestYValue)
return CGRect(origin: origin, size: size)
}

If I did not misunderstand the question, your aim is to find the blue points:
If I'm correct, then it's enough for you to store two points (say topL and topR) and a value (say bottom).
Iteratively:
check if the current point has y < topL.y and eventually update topL and topR.
If instead y == topL.y check if current x is less than topL.x. If yes update topL
otherwise check if current x>topR.x; if yes update topR.
check if current y>bottom. If yes update bottom.
Note that when I say "update topL" I mean both x and y.
At the end you can get your bottom-left and bottom-right points using x coordinate of topL and topR and setting y coordinate to bottom.

If you want, you can use Core Graphics:
let path = CGMutablePath()
path.addLines(between: [p1, p2, p3, p4])
return path.boundingBoxOfPath

Hopefully you're only talking about this one shape, always oriented this way, otherwise this becomes a tricky computational geometry problem (something like the largest enclosed rectangle in a concave polygon).
Given your list of points, the following should work:
a. Find the point with the largest y value.
b. Find the other point with an equally large y value.
c. Compare the x values of these two and determine which is leftmost.
Find the minimum y value of all the points.
Create two new points, each with an x value equal to one of the points you found in step 1, and with the y value found in step 2.
The two points from step 1 are your top left and right points, and the two created in step 3 are the bottom left and right. You can now construct the final rectangle.

Related

How to make a character jump accurate in SceneKit using updateAtTime

I try to make a character jump in SceneKit. I currently have a solution, but I am not happy at all with it.
The character movement is based on the updateAtTime renderer function. There are no SCNActions involved. I want it to be moved only by the updateAtTime function.
My scene is entirely based on Apple's Fox demo Game. But In this Demo Game the Fox Character can only fall from heights - not jump. So I made an adaptation to reverse the fall Function into a jump function. The result is kind of woking, but not accurate. Have a look:
As this image shows, the character currently jumps up in a manner that is against natural laws. It accelerates slowly, then gets faster and faster. (Falling down is okay). I'd like to have my character jump in a nice sinus wave, like the right side of my image illustrates. and as it would be in real nature.
Here is some Code, that makes my character currently jump up and down.
// For Jumping (Falling)
if groundAltitude < position.y - threshold || self.isJumping {
if self.isJumpingUp {
accelerationY -= SCNFloat(deltaTime) * gravityAcceleration // approximation of acceleration for a delta time. UP MOVEMENT
} else {
accelerationY += SCNFloat(deltaTime) * gravityAcceleration // approximation of acceleration for a delta time. DOWN MOVEMENT (Orig Apple)
}
} else {
accelerationY = 0
}
// Set Position
position.y -= accelerationY // ORIG
// reset acceleration if we touch the ground
if groundAltitude > position.y {
accelerationY = 0
position.y = groundAltitude
}
As you can see, I am using the variables isJumping and isJumpingUp to control/define the Y-direction in which the character should be moved. So what I do is setting the isJumping Variable to true and also the isJumpingUp, which makes the Character move up. Then at half the time I set the variable isJumpingUp to false, which will reverse the direction, and brings the character down to the ground level.
This all results in a more or less in an inaccurate jump movement as the image visualises.
Then I found this article on SO: How to make my character jump with gravity?
(It has even the ability to run this code snippet in the Browser.)
And this is very close, if not exactly what I am looking for. (But I am only looking for the Y-direction movement stuff)
But each and every attempt to make a Swift/SceneKit adaptation of this results in a total mess. I don't get it managed to implement into my update function the same way as it behaves on the website. And I don't know what I am doing wrong.
Some attempts made the character to jump up very very fast and then never come down. Or the character did not jump at all. I just have no clue... I would like my character to jump up about 1m to 2m in height and then fall down.
Any help in making my character jump accurately is so much appreciated.
For visualisation purposes - here is my entire Movement Function as it currently is:
func moveCharacter(time: TimeInterval) {
// Delta time since last update
if previousUpdateTime == 0.0 { previousUpdateTime = time }
let deltaTime = Float(min(time - previousUpdateTime, 1.0 / 60))
previousUpdateTime = time // GOOD
groundType = GroundType.inTheAir // always make it in the Air, later change, seems to crash the app ??? oder zufall? - RE-ENABLED for testing
// Speed Control
var characterSpeed = deltaTime * self.speedFactor
let characterRunSpeed = deltaTime * self.speedFactor * 3.4
// Remember initial position
let initialPosition = self.node.position
// Move Character Left or Right
if self.isWalkingLeft { self.node.position = self.node.position - SCNVector3(1.0,0.0,0.0) * characterSpeed}
if self.isWalkingRight { self.node.position = self.node.position + SCNVector3(1.0,0.0,0.0) * characterSpeed}
if self.isRunningLeft { self.node.position = self.node.position - SCNVector3(1.0,0.0,0.0) * characterRunSpeed}
if self.isRunningRight { self.node.position = self.node.position + SCNVector3(1.0,0.0,0.0) * characterRunSpeed}
// Character height positioning
var position = self.node.position
var p0 = position
var p1 = position
let maxRise = SCNFloat(1.0) // orig 0.08
let maxJump = SCNFloat(50.0) // orig 20.0
p0.y -= maxJump
p1.y += maxRise
// Do a vertical ray intersection
let results = gameScene.physicsWorld.rayTestWithSegment(from: p1, to: p0, options:[.collisionBitMask: BitMasks.BitmaskCollision, .searchMode: SCNPhysicsWorld.TestSearchMode.closest])
if let result = results.first {
guard (result.node.geometry != nil) else {return}
let groundAltitude = result.worldCoordinates.y
// can the following if statement be made in other way, because of the new guard?
if (result.node.geometry!.firstMaterial) != nil { groundType = groundTypeFromMaterial(material: result.node.geometry!.firstMaterial!) } else { groundType = .rock }
// MARK: Handle Y Position
let threshold = SCNFloat(1e-5)
let gravityAcceleration = SCNFloat(0.18) // 0.18
if groundAltitude < position.y - threshold || self.isJumping {
if self.isJumpingUp {
accelerationY -= SCNFloat(deltaTime) * gravityAcceleration // approximation of acceleration for a delta time. UP
} else {
accelerationY += SCNFloat(deltaTime) * gravityAcceleration // approximation of acceleration for a delta time. DOWN (Orig)
}
}
else {
accelerationY = 0
}
// Set Position
position.y -= accelerationY // orig.
// reset acceleration if we touch the ground
if groundAltitude > position.y {
accelerationY = 0
position.y = groundAltitude
}
// Finally, update the position of the character.
self.node.position = position
// if not touching the ground, we are in the air.
if groundAltitude < position.y - 0.2 {
groundType = .inTheAir
}
} else {
// no result, we are probably out the bounds of the level -> revert the position of the character.
self.node.position = initialPosition
}
}
Well, after some sleep, and reflecting myself, I came on that solution:
(and it works quite nice)
Added this variables to the class:
let gravityDrag : SCNFloat = 0.9999 // kind of slowing down the jump
let jumpPower : SCNFloat = -0.09 // jumps between 1,5m to 2.0m
Then changed the moveCharacter function like so:
// Calc Y Position with acceleration and gravity
if groundAltitude < position.y - threshold || self.isJumping {
accelerationY += SCNFloat(deltaTime) * gravityAcceleration // approximation of acceleration for a delta time. DOWN (Orig)
accelerationY *= gravityDrag
}
else {
accelerationY = 0
}
// Set Position
position.y -= accelerationY // orig.
// reset acceleration if we touch the ground
if groundAltitude > position.y {
isJumping = false
accelerationY = 0
position.y = groundAltitude
}
Trigger a jump like so:
isJumping = true
accelerationY = jumpPower
Hopefully this will help someone, somewhen.

Swift scene kit - cant apply velocity WHILE doing rotation? Direction is off?

Ok, so Im going straight off Apple's tutorial using a joystick moving an SCNNode for SceneKithere.
I've copied the code and gotten the joystick to both move and rotate the character - but not simultaneously, and not in the right direction relative to the node.
All the correct code is in that download, but what I've done is here is where I get the angle offset of the joystick handle and the float2 from the joystick UI-
characterDirection = float2(Float(padNode.stickPosition.x), -Float(padNode.stickPosition.y))
let direction = theDude.characterDirection(withPointOfView: renderer.pointOfView)
directionAngle = CGFloat(atan2f(direction.x, direction.z))
public func characterDirection(withPointOfView pointOfView: SCNNode?) -> float3 {
let controllerDir = theDude.direction //THIS ISNT BEING UPDATED
if controllerDir.allZero() {
return float3.zero
}
var directionWorld = float3.zero
if let pov = pointOfView {
let p1 = pov.presentation.simdConvertPosition(float3(controllerDir.x, 0.0, controllerDir.y), to: nil)
let p0 = pov.presentation.simdConvertPosition(float3.zero, to: nil)
directionWorld = p1 - p0
directionWorld.y = 0
if simd_any(directionWorld != float3.zero) {
let minControllerSpeedFactor = Float(0.2)
let maxControllerSpeedFactor = Float(1.0)
let speed = simd_length(controllerDir) * (maxControllerSpeedFactor - minControllerSpeedFactor) + minControllerSpeedFactor
directionWorld = speed * simd_normalize(directionWorld)
}
}
return directionWorld
}
I didn't write the last part and still trying to understand it. But what is relevant is I have a float3 and an angle, and they are conflicting when I try to run them both as SCNActions in my renderer update func:
Here is what Apple basically had in update:
// move
if !direction.allZero() {
theDude.characterVelocity = direction * Float(characterSpeed)
var runModifier = Float(1.0)
theDude.walkSpeed = CGFloat(runModifier * simd_length(direction))
// move character - IMPORTANT
theDude.directionAngle = CGFloat(atan2f(direction.x, direction.z))
theDude.node.runAction(SCNAction.move(by: SCNVector3(theDude.characterDirection(withPointOfView: theDude.node)), duration: TimeInterval(40))) //HERE - random time
theDude.isWalking = true
} else {
theDude.isWalking = false
theDude.node.removeAllActions()
}
}
Where on the commented line I applied the move and here Apple had the rotation applied:
var directionAngle: CGFloat = 0.0 {
didSet {
theDude.node.runAction(
SCNAction.rotateTo(x: 0.0, y: directionAngle, z: 0.0, duration: 0.1, usesShortestUnitArc:true))
}
}
They are both happening, problem is I don't know really what to put as my time and my node moves say, left when I have the joystick pointed right, etc because I am not doing the move correctly.
I tried to copy the demo but they have a moving floor, so it is different. What am I doing wrong here?

Take picture from Gallery And Crop that picture in the selected circle portion In Unity 3d?

I am working on a project. I want to take a picture from gallery of android device.
1. How can i take a picture from gallery of android device?
2. How can i Crop the picture selected circle portion in unity3d?
You can use below code for cropping image. I only pass Texture2D and set centre and radius automatically according to texture; but you can pass them manually if you want to.
Texture2D RoundCrop (Texture2D sourceTexture) {
int width = sourceTexture.width;
int height = sourceTexture.height;
float radius = (width < height) ? (width/2f) : (height/2f);
float centerX = width/2f;
float centerY = height/2f;
Vector2 centerVector = new Vector2(centerX, centerY);
// pixels are laid out left to right, bottom to top (i.e. row after row)
Color[] colorArray = sourceTexture.GetPixels(0, 0, width, height);
Color[] croppedColorArray = new Color[width*height];
for (int row = 0; row < height; row++) {
for (int column = 0; column < width; column++) {
int colorIndex = (row * width) + column;
float pointDistance = Vector2.Distance(new Vector2(column, row), centerVector);
if (pointDistance < radius) {
croppedColorArray[colorIndex] = colorArray[colorIndex];
}
else {
croppedColorArray[colorIndex] = Color.clear;
}
}
}
Texture2D croppedTexture = new Texture2D(width, height);
croppedTexture.SetPixels(croppedColorArray);
croppedTexture.Apply();
return croppedTexture;
}

PhysicsJS - How to rotate an element to look at the mouse position

I'm trying to rotate a rectangle to always point at the mouse position.
I've tried this:
document.getElementById('viewport').onmousemove = function(e){
var scratch = Physics.scratchpad();
mousePos = scratch.vector().set(e.x, e.y);
var newAngle = box.state.pos.angle(mousePos);
box.state.angular.pos = newAngle;
scratch.done();
};
Thanks.
Maybe try something like this:
document.getElementById('viewport').onmousemove = function(e){
var scratch = Physics.scratchpad();
// assuming your viewport is the whole screen
mousePos = scratch.vector().set(e.pageX, e.pageY);
mousePos.vsub( box.state.pos ); // get vector pointing towards mouse pos
var newAngle = mousePos.angle(); // get angle with respect to x axis
box.state.angular.pos = newAngle;
scratch.done();
};

Need to make Joystick With Four Directions

Hi. How can I make the joystick which is movable only in four directions? Can anyone give me some suggestions?
Write now I am using this code for joystick. How to make this one to allow only in four directions?
-(void) trackVelocity:(CGPoint) nodeTouchPoint {
CGPoint ankPt = self.anchorPointInPoints;
// Get the touch point relative to the joystick home (anchor point)
CGPoint relPoint = ccpSub(nodeTouchPoint, ankPt);
// Determine the raw unconstrained velocity vector
CGPoint rawVelocity = CGPointMake(relPoint.x / travelLimit.x,relPoint.y / travelLimit.y);
// If necessary, normalize the velocity vector relative to the travel limits
CGFloat rawVelLen = ccpLength(rawVelocity);
velocity = (rawVelLen <= 1.0) ? rawVelocity : ccpMult(rawVelocity, 1.0f/rawVelLen);
// Calculate the vector in angular coordinates
// ccpToAngle returns counterclockwise positive relative to X-axis.
// We want clockwise positive relative to the Y-axis.
CGFloat angle = 90.0- CC_RADIANS_TO_DEGREES(ccpToAngle(velocity));
if(angle > 180.0) {
angle -= 360.0;
}
// angularVelocity.radius = ccpLength(velocity);
// angularVelocity.heading = angle;
// Update the thumb's position, clamping it within the contentSize of the Joystick
[thumbNode setPosition: ccpAdd(ccpCompMult(velocity, travelLimit), ankPt)];
}
Refer the following sample,
https://github.com/jasarien/JSController
It consists of four direction button, free drag view and two buttons, it will be helpful for your question.