Skip to content

Commit

Permalink
minor bug fixes, jupyter-lab support
Browse files Browse the repository at this point in the history
  • Loading branch information
dzufferey committed Dec 28, 2021
1 parent e4933a5 commit d856002
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ project/build.properties

# others
clean.sh
doc/.ipynb_checkpoints/
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,15 @@ If you want to use it in another project, you need to add to your `build.sbt`:
```
resolvers += "jitpack" at "https://jitpack.io"
libraryDependencies += "com.github.dzufferey" %% "scadla" % "0.1.0"
libraryDependencies += "com.github.dzufferey" %% "scadla" % "0.1.1"
```

## JupyterLab

It is possible to use scadla with [JupyterLab](https://jupyter.org/index.html).
First you need to install [Almond](https://almond.sh/).
Then, look in [sample.ipynb](doc/sample.ipynb) to see how it work.


## Contributors

Expand Down
17 changes: 9 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ name := "scadla"

organization := "com.github.dzufferey"

version := "0.1.0"
version := "0.1.1"

scalaVersion := "2.13.4"
scalaVersion := "2.13.6"

scalacOptions in Compile ++= Seq(
scalacOptions ++= Seq(
"-unchecked",
"-deprecation",
"-feature"
Expand All @@ -15,13 +15,14 @@ scalacOptions in Compile ++= Seq(
resolvers += "jitpack" at "https://jitpack.io"

libraryDependencies ++= Seq(
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.0",
"org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2",
"org.scala-lang.modules" %% "scala-xml" % "1.3.0",
"org.scalatest" %% "scalatest" % "3.2.2" % "test",
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.3",
"org.scala-lang.modules" %% "scala-parser-combinators" % "2.0.0",
"org.scala-lang.modules" %% "scala-xml" % "2.0.1",
"org.scalatest" %% "scalatest" % "3.2.5" % "test",
"com.github.dzufferey" %% "misc-scala-utils" % "1.0.0",
"com.github.dzufferey" %% "almond-x3dom-model-viewer" % "0.2.3",
"eu.mihosoft.vrl.jcsg" % "jcsg" % "0.5.7",
"org.typelevel" %% "squants" % "1.7.0"
"org.typelevel" %% "squants" % "1.8.1"
)

fork := true
154 changes: 154 additions & 0 deletions doc/sample.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "55600447-a1ea-4890-b717-cf415fbe85ec",
"metadata": {},
"outputs": [],
"source": [
"import coursierapi._\n",
"interp.repositories() ++= Seq(MavenRepository.of(\"https://jitpack.io\"))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "47708706-19d0-4e4d-883f-14575a7199ce",
"metadata": {},
"outputs": [],
"source": [
"//1. Local version: clone this repository, run `sbt publishLocal`\n",
"//2. Remote version: nothing to do (but you depend on what versions are available)\n",
"import $ivy.`com.github.dzufferey::scadla:0.1.1`"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1517558d-4d31-448f-8345-4edd7ba192cc",
"metadata": {},
"outputs": [],
"source": [
"import scadla._\n",
"import InlineOps._\n",
"import EverythingIsIn.{millimeters, degrees}\n",
"import scadla.backends.OpenSCAD // for rendering (getting a mesh)\n",
"import scadla.backends.almond.Viewer // to show the mesh in jupyter/almond"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f8fd9997-7f2b-453c-9928-98f83b164fdc",
"metadata": {},
"outputs": [],
"source": [
"// exmaple from the README\n",
"val c = Cube(1, 1, 1)\n",
"val s = Sphere(1.5)\n",
"val obj = (c + c.move(-0.5, -0.5, 0)) * s\n",
"val mesh = OpenSCAD(obj) // Solid -> Polyhedron\n",
"Viewer(mesh)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bd783282-7fa5-4777-94ef-5c002e9f547c",
"metadata": {},
"outputs": [],
"source": [
"// a more complex example\n",
"import squants.space.{Length, Angle}\n",
"import scala.language.postfixOps\n",
"import squants.space.LengthConversions._\n",
"import scadla.utils.{RoundedCubeH, Trig, Trapezoid}\n",
"\n",
"// dimensions\n",
"val baseWidth = 95 mm\n",
"val baseLength = 150 mm\n",
"val baseDepth = 5 mm\n",
"\n",
"val overallWidth = 200 mm\n",
"val overallLength = baseLength\n",
"val cornerRadius = 10 mm\n",
"val wall = 2 mm\n",
"val wallStraight = 40 mm\n",
"val wallSlopped = 10 mm\n",
"val wallAngle: Angle = 45\n",
"\n",
"val grooveWidth = 3 mm\n",
"val grooveDepth = 2 mm\n",
"val nbrGrooveH = 12\n",
"val nbrGrooveV = 10\n",
"\n",
"def hat(x: Length, y: Length, z: Length, r: Length, a: Angle) = {\n",
" val d = r*2\n",
" val smaller = z * Trig.sin(a)\n",
" Minkowski(\n",
" Trapezoid((x-d-smaller,x-d,0),(y-d-smaller,y-d,0),z-1),\n",
" Cylinder(r,1)\n",
" ).move(r,r,0)\n",
"}\n",
"\n",
"val base = Union(\n",
" Cube(baseWidth, baseLength, baseDepth).move((overallWidth-baseWidth)/2,(overallLength-baseLength)/2,-baseDepth),\n",
" RoundedCubeH(overallWidth, overallLength, wallStraight, cornerRadius),\n",
" hat(overallWidth, overallLength, wallSlopped, cornerRadius, wallAngle).moveZ(wallStraight)\n",
")\n",
"val sampleGrooveH = Cube(grooveWidth, overallLength - 2*wall - 10, grooveDepth)\n",
"val stepH = (overallWidth - 2*wall - 10) / nbrGrooveH\n",
"val groovesH = for (i <- 1 until nbrGrooveH) yield sampleGrooveH.move(wall + 5 + i * stepH - grooveWidth/2, wall+5, wall)\n",
"val sampleGrooveV = Cube(overallWidth - 2*wall - 10, grooveWidth, grooveDepth)\n",
"val stepV = (overallLength - 2*wall - 10) / nbrGrooveV\n",
"val groovesV = for (i <- 1 until nbrGrooveV) yield sampleGrooveV.move(wall + 5, wall + 5 + i * stepV - grooveWidth/2,wall)\n",
"val shell = Difference(\n",
" base,\n",
" RoundedCubeH(overallWidth - 2*wall, overallLength - 2*wall, wallStraight-wall-grooveDepth, cornerRadius-wall).move(wall,wall,wall+grooveDepth),\n",
" hat(overallWidth - 2*wall, overallLength - 2*wall, wallSlopped, cornerRadius-wall, wallAngle).move(wall,wall,wallStraight),\n",
" Union(groovesH: _*),\n",
" Union(groovesV: _*)\n",
")\n",
"val mesh = OpenSCAD(shell)\n",
"Viewer(mesh)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0b87f12e-127c-47a3-9bb1-17f082b7fdb1",
"metadata": {},
"outputs": [],
"source": [
"// save the object as an STL file\n",
"scadla.backends.stl.Printer.storeBinary(mesh, \"milling_basket.stl\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "174221c4-74f9-42d9-8613-75e972bd3b2f",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Scala",
"language": "scala",
"name": "scala"
},
"language_info": {
"codemirror_mode": "text/x-scala",
"file_extension": ".sc",
"mimetype": "text/x-scala",
"name": "scala",
"nbconvert_exporter": "script",
"version": "2.13.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
5 changes: 4 additions & 1 deletion src/main/scala/scadla/backends/OpenSCAD.scala
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,15 @@ class OpenSCAD(header: List[String], unit: LengthUnit = Millimeters) extends Ren
writer.newLine
}
printWithModules(obj, writer)
writer.flush
}

protected def writeInFile(file: java.io.File, obj: Solid) = {
val writer = new BufferedWriter(new PrintWriter(file))
val fw = new PrintWriter(file)
val writer = new BufferedWriter(fw)
print(obj, writer)
writer.close
fw.close
}

protected def toTmpFile(obj: Solid) = {
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/scadla/backends/ParallelRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ParallelRendererAux[A >: Null](renderer: RendererAux[A], unit: LengthUnit
true
}
protected def setRawResult(p: A): Unit = { res = p }
protected def getRawResult = res
def getRawResult = res
}

def operation(o: Operation, args: Seq[ForkJoinTask[A]]) = new ForkJoinTask[A] {
Expand All @@ -37,7 +37,7 @@ class ParallelRendererAux[A >: Null](renderer: RendererAux[A], unit: LengthUnit
true
}
protected def setRawResult(p: A): Unit = { res = p }
protected def getRawResult = res
def getRawResult = res
}

def transform(t: Transform, arg: ForkJoinTask[A]) = new ForkJoinTask[A] {
Expand All @@ -47,7 +47,7 @@ class ParallelRendererAux[A >: Null](renderer: RendererAux[A], unit: LengthUnit
true
}
protected def setRawResult(p: A): Unit = { res = p }
protected def getRawResult = res
def getRawResult = res
}

def toMesh(t: ForkJoinTask[A]) = renderer.toMesh(t.join)
Expand Down
11 changes: 11 additions & 0 deletions src/main/scala/scadla/backends/almond/Config.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package scadla.backends.almond

import com.github.dzufferey.x3DomViewer.X3D
import scalatags.Text.all._
import squants.space.{Millimeters, LengthUnit}

class Config extends com.github.dzufferey.x3DomViewer.Config {

var shapeAppearance = X3D.appearance(X3D.material(X3D.diffuseColor := "0.7 0.7 0.7"))
val unit: LengthUnit = Millimeters
}
20 changes: 20 additions & 0 deletions src/main/scala/scadla/backends/almond/Viewer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package scadla.backends.almond

import scadla._
import com.github.dzufferey.x3DomViewer.X3D._
import scalatags.Text.all._

object Viewer { // does not extend the normal Viewer class as it needs to return a value

var conf = new Config

def apply(obj: Polyhedron) = {
val (points, faces) = obj.indexed
val indices = faces.map{ case (a,b,c) => s"$a $b $c -1" }.mkString(" ")
val coord = points.map( p => s"${p.x.to(conf.unit)} ${p.y.to(conf.unit)} ${p.z.to(conf.unit)}" ).mkString(" ")
val ifaces = indexedFaceSet(coordIndex := indices.toString, coordinate( point := coord) )
val content = shape(conf.shapeAppearance, ifaces)
com.github.dzufferey.x3DomViewer.Viewer.display(content, conf)
}

}
4 changes: 2 additions & 2 deletions src/main/scala/scadla/backends/stl/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import java.io._
import squants.space.{Length, Millimeters, LengthUnit, SquareMeters}

class AsciiParser(unit: LengthUnit = Millimeters) extends JavaTokenParsers {

def parseVertex: Parser[Point] =
"vertex" ~> repN(3, floatingPointNumber) ^^ {
case List(a, b,c) => Point(unit(a.toDouble), unit(b.toDouble), unit(c.toDouble))
Expand Down Expand Up @@ -77,7 +77,7 @@ class BinaryParser(unit: LengthUnit = Millimeters) {
buffer.position(buffer.position() + 2) //skip attributes
Parser.checkNormal(Face(p1, p2, p3), n)
}
Polyhedron(triangles)
Polyhedron(triangles)
}

}
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/scadla/examples/cnc/ActuatorFastener.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import utils._
import InlineOps._
import thread._
import Common._
import scadla.EverythingIsIn.{millimeters, radians}
import scadla.EverythingIsIn.{millimeters, radians}

// dX, dZ are given from the center of the extrusion
class ActuatorFasterner(dX: Double, dZ: Double) {
Expand All @@ -22,7 +22,7 @@ class ActuatorFasterner(dX: Double, dZ: Double) {
var thread = ISO.M3
var beamConnectorRounding = 2
var nbrScrewsPerSide = 2

def beamConnector = {
val guide = Trapezoid(4.5, 6.5, supportLength, guideDepth, -0.2)
val faceBlank = Union(
Expand Down

0 comments on commit d856002

Please sign in to comment.