Update position of spheres to rotate around a center in jupyter through list? - simulation

Im having difficulties finding a proper function that makes all planets rotate around the sun. I have defined the spheres but am struggling with the execution of their rotation. Would it be effective to make a list in which I update the position of every body? If so how would i tackle this?
def simulate_solar(n, dt):
He = planets_from_file("planeten.txt")
zon = sphere(pos = vector(0,0,0), radius = He[0].straal_v_hemellichaam, color = kleuromzetting(He[0].kleur))
aarde = sphere(pos = vector(-He[3].straal_vd_baan, 0, 0), radius= He[3].straal_v_hemellichaam*50, texture= textures.earth)
maan = sphere(pos = vector(-He[4].straal_vd_baan,0,0), radius = He[4].straal_v_hemellichaam, color = kleuromzetting(He[4].kleur))
mercurius = sphere(pos = vector(-He[1].straal_vd_baan,0,0), radius = He[1].straal_v_hemellichaam, color = kleuromzetting(He[1].kleur))
venus = sphere(pos = vector(-He[2].straal_vd_baan,0,0), radius = He[2].straal_v_hemellichaam, color = kleuromzetting(He[2].kleur))
mars = sphere(pos = vector(-He[5].straal_vd_baan,0,0), radius = He[5].straal_v_hemellichaam, color = kleuromzetting(He[5].kleur))
phobos = sphere(pos = vector(-He[6].straal_vd_baan,0,0), radius = He[6].straal_v_hemellichaam, color = kleuromzetting(He[6].kleur))
deimos = sphere(pos = vector(-He[7].straal_vd_baan,0,0), radius = He[7].straal_v_hemellichaam, color = kleuromzetting(He[7].kleur))
jupiter = sphere(pos = vector(-He[8].straal_vd_baan,0,0), radius = He[8].straal_v_hemellichaam, color = kleuromzetting(He[8].kleur))
io = sphere(pos = vector(-He[9].straal_vd_baan,0,0), radius = He[9].straal_v_hemellichaam, color = kleuromzetting(He[9].kleur))
europa = sphere(pos = vector(-He[10].straal_vd_baan,0,0), radius = He[10].straal_v_hemellichaam, color = kleuromzetting(He[10].kleur))
ganymede = sphere(pos = vector(-He[11].straal_vd_baan,0,0), radius = He[11].straal_v_hemellichaam, color = kleuromzetting(He[11].kleur))
callisto = sphere(pos = vector(-He[12].straal_vd_baan,0,0), radius = He[12].straal_v_hemellichaam, color = kleuromzetting(He[12].kleur))
sim = simulate_solar(365, 24*3600)

Related

Draw a line with a gradient using NSBezierPath, CAShapeLayer, and CAGradientLayer

I have a macOS app where I draw lines and other figures.
I use NSBezierPath to form the lines or figures and then add it to the CAShapeLayer's path and finally, add the CAShapeLayer to the view.
This all works fine and I have a single stroke color. However, I want the lines/figures not to be of a single color but of multiple colors(gradient). I know this can be done through CAGradientLayer and tried a few examples from other SO questions showing iOS variants but they didn't work for me.
Below is a code snippet from the app:
startPoint = point
currentPath = NSBezierPath()
currentShape = CAShapeLayer()
currentShape?.lineWidth = lineWeight
currentShape?.strokeColor = strokeColor.cgColor
currentShape?.fillColor = fillColor.cgColor
currentShape?.lineJoin = CAShapeLayerLineJoin.round
currentShape?.lineCap = CAShapeLayerLineCap.round
currentPath?.move(to: point)
currentPath?.line(to: point)
currentShape?.path = currentPath?.cgPath
view.layer?.addSublayer(currentShape!)
currentGradient = CAGradientLayer()
currentGradient?.mask = currentShape
currentGradient?.frame = currentShape!.frame
currentGradient?.colors = [NSColor.red.cgColor, NSColor.black.cgColor]
view.layer?.addSublayer(currentGradient!)
// some more code here that I omitted (to draw shapes with NSBezierPath)
if let shape = currentShape {
shape.path = currentPath?.cgPath
currentGradient?.mask = shape
currentGradient?.frame = shape.frame
}
If I remove the code that involves currentGradient then I see the lines/figures (in one solid color) but when I add the gradient part, I do not see anything. What am I doing wrong in the above code?
Any help or hints would be really appreciated.
If you have searched, then you know the answer. You cannot stroke a shape with a gradient. Instead, you mask to a gradient; the shape layer becomes the mask whereby the gradient layer is revealed. Example (v is a view in the window):
let grad = CAGradientLayer()
grad.frame = v.bounds
v.layer?.addSublayer(grad)
grad.colors = [NSColor.red.cgColor, NSColor.blue.cgColor]
let shape = CAShapeLayer()
shape.frame = v.bounds
shape.lineWidth = 3
shape.fillColor = NSColor.clear.cgColor
shape.strokeColor = NSColor.black.cgColor
let path = CGPath(ellipseIn: v.bounds.insetBy(dx: 4, dy: 4), transform: nil)
shape.path = path
grad.mask = shape

ARKit –Drop a shadow of 3D object on the plane surface

This is the function that I use to display object on the plane surface.
private func loadScene(path: String) -> SCNNode {
let spotLight = SCNLight()
spotLight.type = SCNLight.LightType.probe
spotLight.spotInnerAngle = 30.0
spotLight.spotOuterAngle = 80.0
spotLight.castsShadow = true
let result = SCNNode()
result.light = spotLight
result.position = SCNVector3(-10.0, 20.0, 10.5)
result.addChildNode(result)
let scene = SCNScene(named: path)!
for node in scene.rootNode.childNodes {
result.addChildNode(node)
}
return result
}
I want to display shadow on the plane surface like this image.
When I set spotlight type like below
spotLight.type = SCNLight.LightType.directional
It shows the object itself with light/dark shadow and does not drop the shadow on the surface.
Can someone please guide me how can I achieve the output as shown in the image?
// To Add Shadow on 3D Model Just Copy Paste this code and it will appear a shadow of 3D Model on Ground
let flourPlane = SCNFloor()
let groundPlane = SCNNode()
let groundMaterial = SCNMaterial()
groundMaterial.lightingModel = .constant
groundMaterial.writesToDepthBuffer = true
groundMaterial.colorBufferWriteMask = []
groundMaterial.isDoubleSided = true
flourPlane.materials = [groundMaterial]
groundPlane.geometry = flourPlane
//
mainNode.addChildNode(groundPlane)
// Create a ambient light
let ambientLight = SCNNode()
ambientLight.light = SCNLight()
ambientLight.light?.shadowMode = .deferred
ambientLight.light?.color = UIColor.white
ambientLight.light?.type = SCNLight.LightType.ambient
ambientLight.position = SCNVector3(x: 0,y: 5,z: 0)
// Create a directional light node with shadow
let myNode = SCNNode()
myNode.light = SCNLight()
myNode.light?.type = SCNLight.LightType.directional
myNode.light?.color = UIColor.white
myNode.light?.castsShadow = true
myNode.light?.automaticallyAdjustsShadowProjection = true
myNode.light?.shadowSampleCount = 64
myNode.light?.shadowRadius = 16
myNode.light?.shadowMode = .deferred
myNode.light?.shadowMapSize = CGSize(width: 2048, height: 2048)
myNode.light?.shadowColor = UIColor.black.withAlphaComponent(0.75)
myNode.position = SCNVector3(x: 0,y: 5,z: 0)
myNode.eulerAngles = SCNVector3(-Float.pi / 2, 0, 0)
// Add the lights to the container
mainNode.addChildNode(ambientLight)
mainNode.addChildNode(myNode)
// End
This edited version of the answer worked for me. I used material with shadowOnly model.
let flourPlane = SCNFloor()
let groundPlane = SCNNode()
let groundMaterial = SCNMaterial()
groundMaterial.lightingModel = .shadowOnly
flourPlane.materials = [groundMaterial]
groundPlane.geometry = flourPlane
//
node.addChildNode(groundPlane)
// Create a ambient light
let ambientLight = SCNNode()
ambientLight.light = SCNLight()
ambientLight.light?.shadowMode = .deferred
ambientLight.light?.color = UIColor.white
ambientLight.light?.type = SCNLight.LightType.ambient
ambientLight.position = SCNVector3(x: 0,y: 5,z: 0)
// Create a directional light node with shadow
let myNode = SCNNode()
myNode.light = SCNLight()
myNode.light?.type = SCNLight.LightType.directional
myNode.light?.color = UIColor.white
myNode.light?.castsShadow = true
myNode.light?.automaticallyAdjustsShadowProjection = true
myNode.light?.shadowSampleCount = 64
myNode.light?.shadowRadius = 16
myNode.light?.shadowMode = .deferred
myNode.light?.shadowMapSize = CGSize(width: 2048, height: 2048)
myNode.light?.shadowColor = UIColor.black.withAlphaComponent(0.75)
myNode.position = SCNVector3(x: 0,y: 1,z: -3)
myNode.eulerAngles = SCNVector3(-Float.pi / 2, 0, 0)
// Add the lights to the container
node.addChildNode(ambientLight)
node.addChildNode(myNode)

How to use SCNAvoidOccluderConstraint (any example)

Does anyone have example of using SCNAvoidOccluderConstraint?
The only description, which I found is:
#abstract A SCNAvoidOccluderConstraint constraints place the receiver
at a position that prevent nodes with the specified category to
occlude the target.
#discussion The target node and it's children are
ignored as potential occluders.
UPDATE: Xcode 9 was officially released and still no one line in documentation.
Coming late, but here is a working example (in Python, but can easily be reproduced in Swift or ObjC). The ball with the SCNAvoidOccluderConstraint on it jumps back on its trajectory whenever the block in the middle obstructs the view to the other ball.
"""
avoid occluder demo
"""
from objc_util import *
import sceneKit as scn
import ui
import math
def dot(v1, v2):
return sum(x*y for x,y in zip(list(v1),list(v2)))
def det2(v1, v2):
return v1[0]*v2[1] - v1[1]*v2[0]
class Demo:
#classmethod
def run(cls):
cls().main()
#on_main_thread
def main(self):
main_view = ui.View()
w, h = ui.get_screen_size()
main_view.frame = (0,0,w,h)
main_view.name = 'avoid occluder demo'
scene_view = scn.View(main_view.frame, superView=main_view)
scene_view.autoresizingMask = scn.ViewAutoresizing.FlexibleHeight | scn.ViewAutoresizing.FlexibleWidth
scene_view.allowsCameraControl = True
scene_view.delegate = self
scene_view.backgroundColor = 'white'
scene_view.rendersContinuously = True
scene_view.scene = scn.Scene()
root_node = scene_view.scene.rootNode
floor_geometry = scn.Floor()
floor_node = scn.Node.nodeWithGeometry(floor_geometry)
root_node.addChildNode(floor_node)
ball_radius = 0.2
ball_geometry = scn.Sphere(radius=ball_radius)
ball_geometry.firstMaterial.diffuse.contents = (.48, .48, .48)
ball_geometry.firstMaterial.specular.contents = (.88, .88, .88)
self.ball_node_1 = scn.Node.nodeWithGeometry(ball_geometry)
self.ball_node_2 = scn.Node.nodeWithGeometry(ball_geometry)
root_node.addChildNode(self.ball_node_1)
root_node.addChildNode(self.ball_node_2)
occluder_geometry = scn.Box(0.3, 2., 15., 0.2)
occluder_geometry.firstMaterial.diffuse.contents = (.91, .91, .91)
occluder_node = scn.Node.nodeWithGeometry(occluder_geometry)
occluder_node.position = (0., 0.8, 0.)
root_node.addChildNode(occluder_node)
self.orbit_r = 10
self.omega_speed_1 = math.pi/1500
self.omega_speed_2 = 1.5*self.omega_speed_1
self.ball_node_1.position = (self.orbit_r, 0.5, 0.)
self.ball_node_2.position = (0., 0.5, self.orbit_r)
constraint = scn.AvoidOccluderConstraint.avoidOccluderConstraintWithTarget(self.ball_node_1)
self.ball_node_2.constraints = [constraint]
camera_node = scn.Node()
camera_node.camera = scn.Camera()
camera_node.position = (0.5*self.orbit_r , 0.5*self.orbit_r, 1.5*self.orbit_r)
camera_node.lookAt(root_node.position)
root_node.addChildNode(camera_node)
light_node = scn.Node()
light_node.position = (self.orbit_r, self.orbit_r, self.orbit_r)
light = scn.Light()
light.type = scn.LightTypeDirectional
light.castsShadow = True
light.shadowSampleCount = 32
light.color = (.99, 1.0, .86)
light_node.light = light
light_node.lookAt(root_node.position)
root_node.addChildNode(light_node)
main_view.present(hide_title_bar=False)
def update(self, view, atTime):
pos_1 = self.ball_node_1.presentationNode.position
pos_2 = self.ball_node_2.presentationNode.position
self.omega_1 = -math.atan2(det2((pos_1.x, pos_1.z), (1., 0.)), dot((pos_1.x, pos_1.z), (1., 0.)))
self.omega_2 = -math.atan2(det2((pos_2.x, pos_2.z), (1., 0.)), dot((pos_2.x, pos_2.z), (1., 0.)))
self.omega_1 += self.omega_speed_1
self.omega_2 += self.omega_speed_2
self.ball_node_1.position = (self.orbit_r*math.cos(self.omega_1), 0.5, self.orbit_r*math.sin(self.omega_1))
self.ball_node_2.position = (self.orbit_r*math.cos(self.omega_2), 0.5, self.orbit_r*math.sin(self.omega_2))
Demo.run()
I came across this oldie recently hoping to get more insight if this constaint could be used to solve a particular problem. Unfortunately, Apple's documentation is still atrocious so I'm leaving some more notes here for posterity.
SCNAvoidOccluderConstraint takes an SCNNode as a target. If an object obstructs the line of sight between the target node and the node that you added this constraint to, the node with the constraint will jump to the nearest point between its original position and the target to re-establish its line of sight with the target node.
In most cases, this point will be immediately on the other side of the obstructing object, so your constrained object will not move all the way through to the other side of the obstructing object; its center point will be aligned with the occluder's visible edge with respect to the target.
Furthermore, you can use a SCNNode's categoryBitMask and the constraint's occluderCategoryBitMask to exclude certain nodes from being occluders.
Here's a loose adaptation of #pulbrich 's original answer in Swift which illustrates the usage. You can paste this in the default XCode SceneKit Game project's GameViewController.swift file:
import SceneKit
import QuartzCore
class GameViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene()
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
cameraNode.look(at: SCNVector3(0,0,0))
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 0)
scene.rootNode.addChildNode(lightNode)
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = .ambient
ambientLightNode.light!.color = NSColor.darkGray
scene.rootNode.addChildNode(ambientLightNode)
let scnView = self.view as! SCNView
scnView.scene = scene
scnView.allowsCameraControl = true
scnView.showsStatistics = true
scnView.backgroundColor = NSColor.black
//--------------------------
let ball_radius = 0.2
let ball_geometry = SCNSphere(radius: ball_radius)
let ball_node_1 = SCNNode.init(geometry: ball_geometry)
ball_node_1.name = "b1"
let ball_node_2 = SCNNode.init(geometry:ball_geometry)
ball_node_2.name = "b2"
scene.rootNode.addChildNode(ball_node_1)
scene.rootNode.addChildNode(ball_node_2)
ball_node_1.worldPosition = SCNVector3(5, 5, 0)
ball_node_2.worldPosition = SCNVector3(5, -5, 0)
let occluder_geometry = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0)
let occluder_node = SCNNode.init(geometry: occluder_geometry)
scene.rootNode.addChildNode(occluder_node)
let constraint = SCNAvoidOccluderConstraint(target: ball_node_1)
ball_node_2.constraints = [constraint]
let a1 = CABasicAnimation(keyPath: "position")
a1.toValue = SCNVector3(-5,5,0)
a1.duration = 5
a1.autoreverses = true
a1.repeatCount = .infinity
ball_node_1.addAnimation(a1, forKey: "move1")
//IMPORTANT NOTE: this constraint will hose CABasicAnimation,
//but the presense of the animation will snap it back to the toValue
//vector when the target is no longer occluded
let a2 = CABasicAnimation(keyPath: "position")
a2.toValue = SCNVector3(5,-5,0)
//a2.toValue = SCNVector3(-5,-5,0)
a2.duration = 5
a2.autoreverses = true
a2.repeatCount = .infinity
ball_node_2.addAnimation(a2, forKey: "move2")
}
}

How do I rotate sprites on a perimeter of a circle towards the center?

I have n sprites on the perimeter of a circle:
let radius = 100
let n = 10
let parentNode = SKSpriteNode(color: NSColor.yellowColor(), size: CGSizeMake(CGFloat(radius), CGFloat(radius)))
parentNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
parentNode.zPosition = 1.5
for sprite in 0...n {
let aSprite = SKSpriteNode(imageNamed: "image.png")
aSprite.setScale(0.15)
aSprite.name = "sprite"+String(sprite)
let theta = Float(Double(sprite) * ((2 * M_PI)/n))
let x = radius * Double(cosf(theta))
let y = radius * Double(sinf(theta))
aSprite.position = CGPointMake(CGFloat(x), CGFloat(y))
parentNode.addChild(aSprite)
}
I want to rotate each sprite towards the center of the circle:
CGPoint(CGRectGetMidX(parentNode.frame),CGRectGetMidY(parentNode.frame))
I tried using atan2 to accomplish this, but it didn't work:
aSprite.zRotation = atan2(CGRectGetMidY(parentNode.frame)-aSprite.position.y, CGRectGetMidX(parentNode.frame) - aSprite.position.x)

Spawning down the middle of the screen

Is there a way to spawn an SKSpriteNode continuously down the middle of the screen. For example I have a circle that I want to spawn in the middle of the x axis and then for that node to spawn all the way down the screen?
These circles are different colours so when they spawn is there a way to randomly change the the colour of the circles when they are spawned?
I understand I can spawn them individually but is there a better way? ( I am using SpriteKit on swift)
You need to learn some basics bruh.
Learn about For loops, arrays and arc4random.
var circleDiameter: CGFloat = 80.0
for var y = self.frame.height; y > 0; y = y - circleDiameter
{
let coloroptions = [UIColor.greenColor(), UIColor.blueColor(), UIColor.redColor()]
let randomNumber = Int(arc4random_uniform(UInt32(coloroptions.count)))
let color = coloroptions[randomNumber]
var rect = CGRectMake(self.frame.width / 2, y, circleDiameter, circleDiameter)
var circle = SKShapeNode()
circle.path = UIBezierPath(ovalInRect: rect).CGPath
circle.fillColor = color
circle.lineWidth = 0
circle.physicsBody = SKPhysicsBody(circleOfRadius: circle.frame.width / 2)
circle.physicsBody?.dynamic = false
self.addChild(circle)
}