I have indoor map and I want to draw path between two route location ex. from A to B I want to draw ARKit based Arrow path in ios Application. Currently I am using ARAnchor to achieve this but challenges is if A to B is 10 meter and I am adding Nodes on each one meter so instead of 10 different nodes i am getting single Arrow nodes showing all 10 in it. I am using below code.
// Below Code from where I am calling addArpath function
if let lat1 = mCurrentPosition?.latitude, let long1 = mCurrentPosition?.longitude {
let latEnd = steplocation.latitude
let longEnd = steplocation.longitude
// if let lastLat = arrpath.last?.latitude,let lastLong = arrpath.last?.longitude,let lastAltitude = arrpath.last?.altitude{
let userLocation = CLLocation(latitude: lat1, longitude: long1)
let endLocation = CLLocation(coordinate: CLLocationCoordinate2DMake(CLLocationDegrees(latEnd), CLLocationDegrees(longEnd)), altitude: CLLocationDistance(steplocation.altitude), horizontalAccuracy: CLLocationAccuracy(5), verticalAccuracy: CLLocationAccuracy(0), course: CLLocationDirection(-1), speed: CLLocationSpeed(5), timestamp: Date())
let heading = getHeadingForDirectionFromCoordinate(from: userLocation, to: endLocation)
let lon1 = degreesToRadians(long1) //DegreesToRadians(long1)
let lon2 = degreesToRadians(longEnd); //DegreesToRadians(longEnd);
let lat2 = degreesToRadians(latEnd);
let dLon = lon2 - lon1
let y = sin(dLon) * cos(lat2);
yVal = yVal + y
// let distanceToendpoint = calculateDistance(lat: endLocation.coordinate.latitude, long: endLocation.coordinate.longitude)
let distvalue = Int(distance) + Int(pathlength)
distance += CGFloat(distvalue)
for i in stride(from: 0, to: distance, by:1) {
print("current loop iteration is:" ,i)
let headingValue = heading - self.heading
zValue = zValue + headingValue
distanceVal = CGFloat(i) + distanceVal
zGlobal = zValue
// Calling addARPathtoLocation
addARPathtoLocation(stepLocation:endLocation,zvalue: zValue, yvalue: yVal, distance:Float(i), direction: manuoverType)
}
// }
}
// MARK: - ARSessionDelegate
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard !(anchor is ARPlaneAnchor) else { return }
let sphereNode = generateArrowNodes(anchor: anchor)
DispatchQueue.main.async {
node.addChildNode(sphereNode)
}
}
//create ARAnchor to add to nodes
func generateArrowNodes(anchor: ARAnchor) -> SCNNode {
let imageMaterial = SCNMaterial()
imageMaterial.isDoubleSided = true
imageMaterial.diffuse.contents = UIImage(named: "blueArrow")
let plane = SCNPlane(width:0.5, height:0.5)
plane.materials = [imageMaterial]
plane.firstMaterial?.isDoubleSided = true
let blueNode = SCNNode(geometry: plane)
blueNode.name = "blueNode"
blueNode.position = SCNVector3(x:Float(zGlobal), y:0, z:Float(distanceVal))
blueNode.eulerAngles.x = -.pi / 2
blueNode.eulerAngles.y -= Float(CGFloat(CGFloat.pi/4*6))
return blueNode
}
func addARPathtoLocation(stepLocation: CLLocation, zvalue: CGFloat, yvalue: CGFloat, distance:Float, direction:VMEManeuverType) {
// give you the depth of anything ARKit has detected
guard let query = sceneView.raycastQuery(from: sceneView.center , allowing: .estimatedPlane, alignment: .any) else {
return
}
let results = sceneView.session.raycast(query)
guard let hitResult = results.first else {
print("No surface found")
return
}
// Add ARAnchor to Scene
let anchor = ARAnchor(transform: hitResult.worldTransform)
sceneView.session.add(anchor: anchor)
}
func radiansToDegrees(_ radians: Double) -> Double {
return (radians) * (180.0 / Double.pi)
}
func degreesToRadians(_ degrees: Double) -> Double {
return (degrees) * (Double.pi / 180.0)
}
func getHeadingForDirectionFromCoordinate(from: CLLocation, to: CLLocation) -> Double {
let fLat = degreesToRadians(from.coordinate.latitude)
let fLng = degreesToRadians(from.coordinate.longitude)
let tLat = degreesToRadians(to.coordinate.latitude)
let tLng = degreesToRadians(to.coordinate.longitude)
let deltaL = tLng - fLng
let x = sin(deltaL) * cos(tLng) //cos(tLat) * sin(deltaL)
let y = cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(deltaL)
let bearing = atan2(x,y)
let bearingInDegrees = bearing.toDegrees
print("Bearing Degrees :",bearingInDegrees) // sanity check
// let degree = radiansToDegrees(atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)))
if bearingInDegrees >= 0 {
return bearingInDegrees
} else {
return bearingInDegrees + 360
}
}