Skip to content

Commit

Permalink
Differentiate atoms by color
Browse files Browse the repository at this point in the history
  • Loading branch information
plweegie committed Dec 18, 2019
1 parent 0ff2b58 commit 55cf324
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 24 deletions.
38 changes: 14 additions & 24 deletions app/src/main/java/com/plweegie/magmolecular/ar/MagMolActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.ar.sceneform.Node
import com.google.ar.sceneform.math.Vector3
import com.google.ar.sceneform.rendering.*
import com.google.ar.sceneform.rendering.Material
import com.google.ar.sceneform.rendering.ShapeFactory
import com.google.ar.sceneform.ux.ArFragment
import com.plweegie.magmolecular.R
import com.plweegie.magmolecular.rendering.AndroidModelBuilder3D
import com.plweegie.magmolecular.utils.ArMolecule
import kotlinx.android.synthetic.main.activity_mag_mol.*
import kotlinx.coroutines.*
import kotlinx.coroutines.future.await
import org.openscience.cdk.DefaultChemObjectBuilder
import org.openscience.cdk.exception.InvalidSmilesException
import org.openscience.cdk.interfaces.IAtom
Expand All @@ -38,7 +39,6 @@ class MagMolActivity : AppCompatActivity() {
private lateinit var arFragment: ArFragment

private var smiles: String? = null
private var sphereRenderable: ModelRenderable? = null

private val renderableJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + renderableJob)
Expand All @@ -62,32 +62,27 @@ class MagMolActivity : AppCompatActivity() {
private suspend fun parseSmiles(smiles: String?) {
loading_pb?.visibility = View.VISIBLE

sphereRenderable = getModelRenderable(this@MagMolActivity)
try {
val atomContainer = smilesParser.parseSmiles(smiles)

sphereRenderable?.let {
try {
val atomContainer = smilesParser.parseSmiles(smiles)
val atoms3d = get3DCoordinates(atomContainer)
val arMolecule = ArMolecule(atoms3d, this)

val atoms3d = get3DCoordinates(atomContainer)
atoms3d.forEach { atom ->
with(atom.point3d) {
val coords = Vector3(x.toFloat(), y.toFloat(), z.toFloat())
addRenderable(coords)
}
}

} catch (e: InvalidSmilesException) {
Toast.makeText(this, "Invalid SMILES", Toast.LENGTH_SHORT).show()
arMolecule.renderableAtoms.forEach { (atom, material) ->
val coords = Vector3(atom.xCoord, atom.yCoord, atom.zCoord)
addRenderable(coords, material.await())
}
} catch (e: InvalidSmilesException) {
Toast.makeText(this, "Invalid SMILES", Toast.LENGTH_SHORT).show()
}
}

private fun addRenderable(position: Vector3) {
private fun addRenderable(position: Vector3, material: Material) {
loading_pb?.visibility = View.GONE

val node = Node().apply {
worldPosition = Vector3.subtract(position.scaled(0.05f), Vector3(0.0f, 0.2f, 0.5f))
renderable = sphereRenderable
renderable = ShapeFactory.makeSphere(0.05f, Vector3.zero(), material)
}

arFragment.arSceneView.scene.addChild(node)
Expand All @@ -100,11 +95,6 @@ class MagMolActivity : AppCompatActivity() {
return atomContainer3D.atoms().toList()
}

private suspend fun getModelRenderable(context: Context): ModelRenderable {
val material = MaterialFactory.makeOpaqueWithColor(context, Color(android.graphics.Color.BLACK)).await()
return ShapeFactory.makeSphere(0.05f, Vector3.zero(), material)
}

override fun onDestroy() {
super.onDestroy()
renderableJob.cancel()
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/java/com/plweegie/magmolecular/utils/ArAtom.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.plweegie.magmolecular.utils

import android.graphics.Color


data class ArAtom(val xCoord: Float,
val yCoord: Float,
val zCoord: Float,
private val element: String) {

companion object {
private val COLOR_MAPPINGS: HashMap<String, Int> = hashMapOf(
"C" to Color.BLACK,
"O" to Color.RED,
"N" to Color.BLUE,
"Cl" to Color.GREEN,
"S" to Color.YELLOW,
"P" to Color.parseColor("#FFA500"),
"Br" to Color.parseColor("maroon"),
"I" to Color.parseColor("fuchsia"),
"F" to Color.parseColor("#BFFF00")
)
}

val color: Int = COLOR_MAPPINGS[element] ?: Color.BLACK
}
31 changes: 31 additions & 0 deletions app/src/main/java/com/plweegie/magmolecular/utils/ArMolecule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.plweegie.magmolecular.utils

import android.content.Context
import com.google.ar.sceneform.rendering.Material
import com.google.ar.sceneform.rendering.MaterialFactory
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.future.asDeferred
import org.openscience.cdk.interfaces.IAtom


class ArMolecule(atoms: List<IAtom>, private val context: Context) {

val centerCoordX: Float = (atoms.sumByDouble { it.point3d.x } / atoms.size).toFloat()
val centerCoordY: Float = (atoms.sumByDouble { it.point3d.y } / atoms.size).toFloat()
val centerCoordZ: Float = (atoms.sumByDouble { it.point3d.z } / atoms.size).toFloat()

private val arAtoms: List<ArAtom> = atoms.map { atom ->
with(atom.point3d) {
ArAtom(x.toFloat(), y.toFloat(), z.toFloat(), atom.symbol)
}
}

private val materials: List<Deferred<Material>> = arAtoms.map {
getMaterialAsync(it.color)
}

val renderableAtoms: List<Pair<ArAtom, Deferred<Material>>> = arAtoms zip materials

private fun getMaterialAsync(color: Int): Deferred<Material> =
MaterialFactory.makeOpaqueWithColor(context, com.google.ar.sceneform.rendering.Color(color)).asDeferred()
}

0 comments on commit 55cf324

Please sign in to comment.