Remove all grid lines in ios-charts - ios-charts

I already have
let chartView = LineChartView()
chartView.rightAxis.enabled = false
chartView.leftAxis.enabled = false
chartView.drawBordersEnabled = false
This chart is simply sample data:
let values = (0..<30).map { (i) -> ChartDataEntry in
let val = Double(arc4random_uniform(420) + 3)
return ChartDataEntry(x: Double(i), y: val)
}
I simply want a line graph here with no scale or delimiting at all

Remove the vertical grid lines by hiding the gridlines on the xAxis:
chartView.xAxis.drawGridLinesEnabled = false
Remove the x Axis line and y Axis:
chartView.xAxis.drawAxisLineEnabled = false
chartView.leftAxis.drawAxisLineEnabled = false
This will result in a line chart that is just a line without any units or scale:

Related

SCNNode SCNAction.move(to:) not running but being called - Swift

I am aiming to move the inhabitants in a scene randomly around inside a bounded area. Every 3 seconds the x, y, and z positions of the SCNVector3 are changed then the node moves to those points.
The problem im having is the nodes are not moving to those points. The points change as seen in the print("running: x\(self.x) y\(self.y) z\(self.z) on - \(node.name!)") line. I assume the SCNAction.move(to:) action is being called but for some reason that line does nothing.
No errors are being thrown the nodes just spawn at the random point and never move.
This is the code I have to achive the current movements:
var x = Float.random(in: -0.25...0.265)
var y:Float = 0
var z = Float.random(in: -0.3...0.215)
func spawnInhabitants() {
let type = skyBalls[_index].getInhabitantType().rawValue
let scene = SCNScene(named: "art.scnassets/inhabitants/\(type).scn")!
let inhabitantNode:SCNNode = scene.rootNode.childNode(withName: type, recursively: false)!
inhabitantNode.scale = SCNVector3(0.000075, 0.000075, 0.000075)
inhabitantNode.physicsBody?.physicsShape = SCNPhysicsShape(node: inhabitantNode)
inhabitantNode.physicsBody?.type = .dynamic
inhabitantNode.physicsBody?.isAffectedByGravity = false
inhabitantNode.physicsBody?.categoryBitMask = 1
inhabitantNode.physicsBody?.collisionBitMask = 6
inhabitantNode.physicsBody?.contactTestBitMask = 1
for inhab in skyBalls[_index].getInhabitants() {
x = Float.random(in: -0.25...0.265)
y = 0
z = Float.random(in: -0.3...0.215)
inhabitantNode.position = SCNVector3(x, y, z)
let move_around = SCNAction.run { node in
self.x = Float.random(in: -0.25...0.265)
self.y = 0
self.z = Float.random(in: -0.3...0.215)
print("running: x\(self.x) y\(self.y) z\(self.z) on - \(node.name!)")
}
let move = SCNAction.move(to: SCNVector3(x, y, z), duration: 3) //<- This is the problem
let seq = SCNAction.sequence([move_around, move])
let i = skyBalls[_index].getInhabitants().firstIndex(of: inhab)
inhabitantNode.name = "\(type)\(i!)"
inhabitantNode.runAction(SCNAction.repeatForever(seq))
colonyScene.rootNode.addChildNode(inhabitantNode.copy() as! SCNNode)
}
}
As a note:
skyBalls[_index].getInhabitantType().rawValue
^Returns a String of the enum type for the inhabitant (mostly used for naming)
skyBalls[_index].getInhabitants()
^returns the list of inhabitants form the instance of skyBalls and an index. more specifically an array of inhabitants.
colonyScene
^This is the SCNScene for the view.
Thanks in advance.
Your move action might be using x, y, z values at the time the action is created. So you instead might try to create a new action inside of the run action after generating random values... (I simplified your code snippet to test this approach)
for inhab in skyBalls {
inhab.position = SCNVector3(x, y, z)
let move_around = SCNAction.run { node in
self.x = Float.random(in: -0.25...0.265)
self.y = 0
self.z = Float.random(in: -0.3...0.215)
print("running: x\(self.x) y\(self.y) z\(self.z) on - \(node.name)")
let moveAction = SCNAction.move(to: SCNVector3(self.x, self.y, self.z), duration: 3)
node.runAction(moveAction)
}
let wait = SCNAction.wait(duration: 3) // make same as moveAction duration
//let move = SCNAction.move(to: SCNVector3(x, y, z), duration: 3) //<- This is the problem
let seq = SCNAction.sequence([move_around, wait])
inhab.runAction(SCNAction.repeatForever(seq))
scnView.scene!.rootNode.addChildNode(inhab)
}
Hope this helps

Local Binary Patterns features

I have a dataset of images that differ in sizes, and when I extract the local binary pattern (uniform local binary 59 feature) from them I get several features as zeros, is it acceptable as features, if not, and how to deal with it
You can use this solution: https://github.com/arsho/local_binary_patterns
def get_pixel(img, center, x, y):
new_value = 0
try:
if img[x][y] >= center:
new_value = 1
except:
pass
return new_value
def lbp_calculated_pixel(img, x, y):
center = img[x][y]
val_ar = []
val_ar.append(get_pixel(img, center, x-1, y+1)) # top_right
val_ar.append(get_pixel(img, center, x, y+1)) # right
val_ar.append(get_pixel(img, center, x+1, y+1)) # bottom_right
val_ar.append(get_pixel(img, center, x+1, y)) # bottom
val_ar.append(get_pixel(img, center, x+1, y-1)) # bottom_left
val_ar.append(get_pixel(img, center, x, y-1)) # left
val_ar.append(get_pixel(img, center, x-1, y-1)) # top_left
val_ar.append(get_pixel(img, center, x-1, y)) # top
power_val = [1, 2, 4, 8, 16, 32, 64, 128]
val = 0
for i in range(len(val_ar)):
val += val_ar[i] * power_val[i]
return val
# Function to generate horizontal projection profile
def getHorizontalProjectionProfile(image):
# Convert black spots to ones
image[image == 0] = 1
# Convert white spots to zeros
image[image == 255] = 0
horizontal_projection = np.sum(image, axis = 1)
return horizontal_projection
# Function to generate vertical projection profile
def getVerticalProjectionProfile(image):
# Convert black spots to ones
image[image == 0] = 1
# Convert white spots to zeros
image[image == 255] = 0
vertical_projection = np.sum(image, axis = 0)
return vertical_projection
lenx = x_train.shape[0]
x_train_lbp = np.zeros((lenx, 32,32))
for NUM in range(lenx):
gray = rgb2gray(x_train[NUM])
for i in range(0, 32):
for j in range(0, 32):
x_train_lbp[NUM][i][j] = lbp_calculated_pixel(gray, i, j)
lenx = x_test.shape[0]
x_test_lbp = np.zeros((lenx, 32,32))
for NUM in range(lenx):
gray = rgb2gray(x_test[NUM])
for i in range(0, 32):
for j in range(0, 32):
x_test_lbp[NUM][i][j] = lbp_calculated_pixel(gray, i, j)
from sklearn import preprocessing
lenx = x_train.shape[0]
x_train_lbp_vector = np.zeros((lenx, 64))
for NUM in range(lenx):
horizontal_projection = getHorizontalProjectionProfile(x_train_lbp[NUM])
vertical_projection = getVerticalProjectionProfile(x_train_lbp[NUM])
x_train_lbp_vector[NUM] = np.concatenate((horizontal_projection, vertical_projection), axis=0)
x_train_lbp_vector[NUM] = normalize(x_train_lbp_vector[NUM].reshape(1, -1))
lenx = x_test.shape[0]
x_test_lbp_vector = np.zeros((lenx, 64))
for NUM in range(lenx):
horizontal_projection = getHorizontalProjectionProfile(x_test_lbp[NUM])
vertical_projection = getVerticalProjectionProfile(x_test_lbp[NUM])
x_test_lbp_vector[NUM] = np.concatenate((horizontal_projection, vertical_projection), axis=0)
x_test_lbp_vector[NUM] = normalize(x_test_lbp_vector[NUM].reshape(1, -1))

Procedural mesh not rendering lighting [SceneKit - Xcode]

I am quite new to swift and Xcode however, I have been programming in other languages for several years. I am trying to procedurally create a 3D mesh in SceneKit (iOS). My code works as expected however, when running the application the generated object renders a flat black colour, ignoring all lighting. I have also added a cube to the scene to show that the scene lighting is working.
I would imagine that there is either a problem with the shader or that I need to define the normals of the geometry to fix this. I have tried playing around with a few properties of the SCNMaterial, but they don't seem to change anything.
If it is just a case of defining the normals, please could you advise how I would do this in Swift / SceneKit. Or perhaps I have missed something else, any help would be much appreciated.
Screenshot below:
My code below:
public static func CreateMesh (size: CGFloat, resolution: CGFloat) -> SCNNode? {
let axisCount = Int(floor(size / resolution))
let bottomLeft = CGVector(
dx: CGFloat(-(axisCount / 2)) * resolution,
dy: CGFloat(-(axisCount / 2)) * resolution
)
var verts = Array(
repeating: Array(
repeating: (i: Int(0), pos: SCNVector3.init(x: 0, y: 0, z: 0)),
count: axisCount),
count: axisCount
)
var vertsStream = [SCNVector3]()
var i : Int = 0
for x in 0...axisCount-1 {
for y in 0...axisCount-1 {
verts[x][y] = (
i,
SCNVector3(
x: Float(bottomLeft.dx + CGFloat(x) * resolution),
y: Float.random(in: 0..<0.1),
z: Float(bottomLeft.dy + CGFloat(y) * resolution)
)
)
vertsStream.append(verts[x][y].pos)
i += 1
}
}
var tris = [(a: Int, b: Int, c: Int)]()
var trisStream = [UInt16]()
for x in 0...axisCount - 2 {
for y in 0...axisCount - 2 {
// Quad
tris.append((
a: verts[x][y].i,
b: verts[x][y+1].i,
c: verts[x+1][y+1].i
))
tris.append((
a: verts[x+1][y+1].i,
b: verts[x+1][y].i,
c: verts[x][y].i
))
}
}
for t in tris {
trisStream.append(UInt16(t.a))
trisStream.append(UInt16(t.b))
trisStream.append(UInt16(t.c))
}
// Create scene element
let geometrySource = SCNGeometrySource(vertices: vertsStream)
let geometryElement = SCNGeometryElement(indices: trisStream, primitiveType: .triangles)
let geometryFinal = SCNGeometry(sources: [geometrySource], elements: [geometryElement])
let node = SCNNode(geometry: geometryFinal)
////////////////////////
// FIX MATERIAL
////////////////////////
let mat = SCNMaterial()
mat.diffuse.intensity = 1
mat.lightingModel = .blinn
mat.blendMode = .replace
node.geometry?.materials = [mat]
return node
}
After a lot of searching I managed to find a post with a line of code that looks something like this:
let gsNormals = SCNGeometrySource(normals: normalStream)
So from there I managed to work out how to set the surface normals. It seems like there really isn't a lot of online content / learning material when it comes to the more advanced topics like this in Xcode / Swift, which is quite unfortunate.
I have set it up to create a parabolic shape plane, just for testing. But this code will be used to generate a mesh from a height map, which should now be easy to implement. I think it's pretty useful code, so I have included it below incase anyone else ever has the same issue that I did.
public static func CreateMesh (size: CGFloat, resolution: CGFloat) -> SCNNode? {
let axisCount = Int(floor(size / resolution))
let bottomLeft = CGVector(
dx: CGFloat(-(axisCount / 2)) * resolution,
dy: CGFloat(-(axisCount / 2)) * resolution
)
/// Verticies ///
var verts = Array(
repeating: Array(
repeating: (i: Int(0), pos: SCNVector3.init(x: 0, y: 0, z: 0)),
count: axisCount),
count: axisCount
)
var vertsStream = [SCNVector3]()
var i = 0
for x in 0...axisCount - 1 {
for y in 0...axisCount - 1 {
var dx = axisCount / 2 - x
dx = dx * dx
var dy = axisCount / 2 - y
dy = dy * dy
let yVal = Float(Double(dx + dy) * 0.0125)
verts[x][y] = (
i: i,
pos: SCNVector3(
x: Float(bottomLeft.dx + CGFloat(x) * resolution),
//y: Float.random(in: 0..<0.1),
y: yVal,
z: Float(bottomLeft.dy + CGFloat(y) * resolution)
)
)
vertsStream.append(verts[x][y].pos)
i += 1
}
}
///
/// Triangles ///
var tris = [(a: Int, b: Int, c: Int)]()
var trisStream = [UInt32]()
for x in 0...axisCount - 2 {
for y in 0...axisCount - 2 {
// Quad
tris.append((
a: verts[x][y].i,
b: verts[x][y+1].i,
c: verts[x+1][y].i
))
tris.append((
a: verts[x+1][y].i,
b: verts[x][y+1].i,
c: verts[x+1][y+1].i
))
}
}
for t in tris {
trisStream.append(UInt32(t.a))
trisStream.append(UInt32(t.b))
trisStream.append(UInt32(t.c))
}
///
/// Normals ///
var normalStream = [SCNVector3]()
for x in 0...axisCount - 1 {
for y in 0...axisCount - 1 {
// calculate normal vector perp to average plane
let leftX = x == 0 ? 0 : x - 1
let rightX = x == axisCount - 1 ? axisCount - 1 : x + 1
let leftY = y == 0 ? 0 : y - 1
let rightY = y == axisCount - 1 ? axisCount - 1 : y + 1
let avgXVector = float3(verts[rightX][y].pos) - float3(verts[leftX][y].pos)
let avgYVector = float3(verts[x][rightY].pos) - float3(verts[x][leftY].pos)
// If you are unfamiliar with how to calculate normals
// search for vector cross product, this is used to find
// a vector that is orthogonal to two other vectors, in our
// case perpendicular to the surface
let normal = cross(
normalize(avgYVector),
normalize(avgXVector)
)
normalStream.append(SCNVector3(normal))
}
}
///
// Create scene element
let gsGeometry = SCNGeometrySource(vertices: vertsStream)
let gsNormals = SCNGeometrySource(normals: normalStream)
let geometryElement = SCNGeometryElement(indices: trisStream, primitiveType: .triangles)
let geometryFinal = SCNGeometry(sources: [gsGeometry, gsNormals], elements: [geometryElement])
let node = SCNNode(geometry: geometryFinal)
let mat = SCNMaterial()
mat.isDoubleSided = true
mat.lightingModel = .blinn
node.geometry?.materials = [mat]
return node
}

Extract Float array from Data

I have a function that receives a Data object together with a width and height. The data is a so called "normalised" image in binary form.
Each pixel consists out of 3 Float values for the R, G, B colors ranging from 0 -> 1.0 (instead of the typical 0-255 for UInt8 values, but here we have floats). In fact its a sort of 2 dimensional array with a width and a height like this:
How can extract the R, G, B values as Swift floats from the Data object? This is what I came up with so far:
func convert(data: Data, width: Int, height: Int) {
let sizeFloat = MemoryLayout.size(ofValue: CGFloat.self)
for x in 0...width {
for y in 0...height {
let index = ( x + (y * width) ) * sizeFloat * 3
let dataIndex = Data.Index(???)
data.copyBytes(to: <#T##UnsafeMutableBufferPointer<DestinationType>#>??, from: <#T##Range<Data.Index>?#>???)
let Red = ....
let Green = ...
let Blue = ...
}
}
}
You can use withUnsafeBytes() to access the raw data as an array of Float values:
func convert(data: Data, width: Int, height: Int) {
data.withUnsafeBytes { (floatPtr: UnsafePointer<Float>) in
for x in 0..<width {
for y in 0..<height {
let index = (x + y * width) * 3
let red = floatPtr[index]
let green = floatPtr[index+1]
let blue = floatPtr[index+2]
// ...
}
}
}
}
var r= data[0];
var g = data[1];
var b = data[2];
element.background-color =rgba(r,g,b,1)
perhaps your looking for something like this?

Move y axis labels to left side of heatmap.2

I would like to move the y-axis labels to the left side of heatmap.2. (This is similar, but not the same, as the question regarding moving the axis on heatmap)
While I am able to move the axis by editing line 290 of the heatmap.2 function, it the values then overwrite the actual heatmap.
if (is.null(srtRow) && is.null(colRow)) {
axis(4, iy, labels = labRow, las = 2, line = -0.5 + offsetRow,
tick = 0, cex.axis = cexRow, hadj = adjRow[1], padj = adjRow[2])
}
else {
if (is.null(srtRow) || is.numeric(srtRow)) {
xpd.orig <- par("xpd")
par(xpd = NA)
ypos <- axis(4, iy, labels = rep("", nr), las = 2, #change
line = -0.5, tick = 0)
text(x = par("usr")[2] + (1 + offsetRow) * strwidth("M"),
y = ypos, labels = labRow, adj = adjRow, cex = cexRow,
srt = srtRow, col = colRow)
par(xpd = xpd.orig)
}
I tried moving the location of the heatmap.2 by mucking about with the lwid and lhei options, but the overwrite problem persisted.
Thank you
Eric