kotlin-graphics / assimp

JVM Open Asset Import Library (Assimp)
Other
95 stars 28 forks source link

kotlin.KotlinNullPointerException when importing step file #19

Open jimmyd-be opened 6 years ago

jimmyd-be commented 6 years ago

I'm creating a POC for visualizing STP files in a Java application. I try to import the step file using the Importer().readFile() method and this gives a

Exception in thread "main" kotlin.KotlinNullPointerException
    at uno.kotlin.UtilKt.getUrl(util.kt:22)
    at uno.kotlin.UtilKt.getUri(util.kt:21)
    at assimp.Importer.readFile(Importer.kt:308)

This by only set this line of code: AiScene scene = new Importer().readFile(fileName, 0); fileName variable is the full path to the stp file.

Wasabi375 commented 6 years ago

I don't think we have an Importer implemented for step files (yet). I can't however recreate the NPE. What version of assimp are you using? AFAIK (and according to my tests) you should see a kotlin.NotImplementedError which I just changed to a proper error message.

skalarproduktraum commented 5 years ago

Hi there! The issue here I am also seeing, and it is independent of the file you are importing: The reason it is occuring is that String.url and String.uri are defined as

val String.uri get() = url.toURI()!!
val String.url get() = ClassLoader.getSystemResource(this)!!

This in turn means that you are trying to use the system classloader to get the path to the file, which only works if the file is actually in the class path -- and that is most likely not the case if the file name comes e.g. from a file open dialog -- otherwise getSystemResource() will return null, which is seen here.

Getting from a String to an URI/URL in Java is however not super-straightforward, and you need to take the different platforms into consideration. One way to solve this is to convert the String to a Path, and get the URL/URI from that. We are doing that in scenery in this way:

fun getPath(path: URI): Path {
            return try {
                Paths.get(path)
            } catch (e: FileSystemNotFoundException) {
                val env: Map<String, Any> = emptyMap()
                try {
                    val fs = FileSystems.newFileSystem(path, env)

                    fs.provider().getPath(path)
                } catch(pnfe: ProviderNotFoundException) {
                    FileSystems.getDefault().getPath(path.toString())
                }
            } catch (e : IllegalArgumentException) {
                // handle the case when no scheme is given
                when(ExtractsNatives.getPlatform()) {
                    // on macOS and Linux, we'll just use the default file system and hand over the scheme-less path
                    ExtractsNatives.Platform.MACOS,
                    ExtractsNatives.Platform.LINUX -> FileSystems.getDefault().getPath(path.toString())
                    // on Windows, a leading slash is added, which we remove
                    ExtractsNatives.Platform.WINDOWS -> FileSystems.getDefault().getPath(path.toString().substring(1))
                    else -> {
                        throw IllegalStateException("Don't know how to sanitize path $path on unknown platform.")
                    }
                }
            }
        }
Wasabi375 commented 5 years ago

Woops, your right. I'll look into it. Seems like there are still some more temporary utility function used. Thanks for the code snippet.