From 55cf3240665f6829f0be3d21068345e721c1e2b4 Mon Sep 17 00:00:00 2001 From: Jszymanski Date: Wed, 18 Dec 2019 22:52:50 +0100 Subject: [PATCH] Differentiate atoms by color --- .../magmolecular/ar/MagMolActivity.kt | 38 +++++++------------ .../com/plweegie/magmolecular/utils/ArAtom.kt | 26 +++++++++++++ .../plweegie/magmolecular/utils/ArMolecule.kt | 31 +++++++++++++++ 3 files changed, 71 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/com/plweegie/magmolecular/utils/ArAtom.kt create mode 100644 app/src/main/java/com/plweegie/magmolecular/utils/ArMolecule.kt diff --git a/app/src/main/java/com/plweegie/magmolecular/ar/MagMolActivity.kt b/app/src/main/java/com/plweegie/magmolecular/ar/MagMolActivity.kt index bf8856f..b2b0aea 100644 --- a/app/src/main/java/com/plweegie/magmolecular/ar/MagMolActivity.kt +++ b/app/src/main/java/com/plweegie/magmolecular/ar/MagMolActivity.kt @@ -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 @@ -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) @@ -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) @@ -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() diff --git a/app/src/main/java/com/plweegie/magmolecular/utils/ArAtom.kt b/app/src/main/java/com/plweegie/magmolecular/utils/ArAtom.kt new file mode 100644 index 0000000..eff0b6d --- /dev/null +++ b/app/src/main/java/com/plweegie/magmolecular/utils/ArAtom.kt @@ -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 = 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 +} \ No newline at end of file diff --git a/app/src/main/java/com/plweegie/magmolecular/utils/ArMolecule.kt b/app/src/main/java/com/plweegie/magmolecular/utils/ArMolecule.kt new file mode 100644 index 0000000..aa09f32 --- /dev/null +++ b/app/src/main/java/com/plweegie/magmolecular/utils/ArMolecule.kt @@ -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, 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 = atoms.map { atom -> + with(atom.point3d) { + ArAtom(x.toFloat(), y.toFloat(), z.toFloat(), atom.symbol) + } + } + + private val materials: List> = arAtoms.map { + getMaterialAsync(it.color) + } + + val renderableAtoms: List>> = arAtoms zip materials + + private fun getMaterialAsync(color: Int): Deferred = + MaterialFactory.makeOpaqueWithColor(context, com.google.ar.sceneform.rendering.Color(color)).asDeferred() +} \ No newline at end of file