fixed merge conflicts
|
|
@ -39,6 +39,13 @@
|
|||
<script src="{{ base_url }}/js/jquery-2.1.1.min.js"></script>
|
||||
<script src="{{ base_url }}/js/modernizr-2.8.3.min.js"></script>
|
||||
<script type="text/javascript" src="{{ base_url }}/js/highlight.pack.js"></script>
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
{% if page and page.title == 'Examples' %}
|
||||
<script src="{{ base_url }}/js/three.js"></script>
|
||||
<script src="{{ base_url }}/js/PLYLoader.js"></script>
|
||||
{% endif %}
|
||||
>>>>>>> master
|
||||
{%- endblock %}
|
||||
|
||||
{%- block extrahead %} {% endblock %}
|
||||
|
|
@ -102,6 +109,12 @@
|
|||
{% block content %}
|
||||
{{ page.content }}
|
||||
{% endblock %}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
{% if page and page.title == 'Examples' %}
|
||||
{% include "scans.html" %}
|
||||
{% endif %}
|
||||
>>>>>>> master
|
||||
</div>
|
||||
</div>
|
||||
{%- block footer %}
|
||||
|
|
|
|||
185
docs-theme/scans.html
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
<!-- Div which will hold the Output -->
|
||||
<div id="WebGL-output">
|
||||
<div id="loading-indicator">
|
||||
<div class="sk-three-bounce">
|
||||
<div class="sk-child sk-bounce1"></div>
|
||||
<div class="sk-child sk-bounce2"></div>
|
||||
<div class="sk-child sk-bounce3"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="example-preview">
|
||||
<li><img id="duck-example" src="../examples/duck/duck.png"><a href="../examples/duck/duck_pointcloud.ply">Download</a></li><!--
|
||||
--><li><img id="bear-example" src="../examples/bear/bear.png"><a href="../examples/bear/bear_pointcloud.ply">Download</a></li><!--
|
||||
--><li><img id="glue-stick-example" src="../examples/glue_stick/glue_stick.png"><a href="../examples/glue_stick/glue_stick_pointcloud.ply">Download</a></li><!--
|
||||
--><li><img id="sculpture-example" src="../examples/sculpture/sculpture.png"><a href="../examples/sculpture/sculpture_pointcloud.ply">Download</a></li><!--
|
||||
--><li><img id="seal-example" src="../examples/seal/seal.png"><a href="../examples/seal/seal_pointcloud.ply">Download</a></li>
|
||||
</ul>
|
||||
<!-- Javascript code that runs our Three.js examples -->
|
||||
<script type="text/javascript">
|
||||
|
||||
var camera, cameraTarget, scene, renderer;
|
||||
var cameraDistance = 150;
|
||||
var loader;
|
||||
var loadGeometry;
|
||||
var model;
|
||||
var indicator = $('#loading-indicator');
|
||||
indicator.show();
|
||||
|
||||
init();
|
||||
animate();
|
||||
|
||||
|
||||
function init() {
|
||||
|
||||
container = document.getElementById( 'WebGL-output' );
|
||||
|
||||
camera = new THREE.PerspectiveCamera( 45, container.clientWidth / (container.clientWidth*0.6), 1, 2000 );
|
||||
camera.position.set( cameraDistance, 0, 0 );
|
||||
|
||||
cameraTarget = new THREE.Vector3( 0, 0, 0 );
|
||||
|
||||
scene = new THREE.Scene();
|
||||
scene.fog = new THREE.Fog( 0x72645b, 200, 600 );
|
||||
|
||||
|
||||
// Ground
|
||||
geometry = new THREE.CylinderGeometry( 70, 70, 2, 32 );
|
||||
material = new THREE.MeshBasicMaterial( {color: 0xDEDEDE} );
|
||||
turntable = new THREE.Mesh( geometry, material );
|
||||
turntable.name = "turntable";
|
||||
scene.add( turntable );
|
||||
|
||||
|
||||
// PLY file
|
||||
|
||||
loader = new THREE.PLYLoader();
|
||||
loader.useColor = true;
|
||||
loader.colorsNeedUpdate = true;
|
||||
loadGeometry = function ( geometry ) {
|
||||
|
||||
if(model) {
|
||||
scene.remove(model);
|
||||
}
|
||||
var material = new THREE.PointsMaterial({
|
||||
size: 2,
|
||||
vertexColors : THREE.VertexColors
|
||||
});
|
||||
model = new THREE.Points(geometry, material);
|
||||
model.rotateX(-Math.PI/2);
|
||||
model.geometry.computeBoundingSphere();
|
||||
model.geometry.computeBoundingBox();
|
||||
camera.position.y = model.geometry.boundingSphere.center.z*1.2;
|
||||
cameraTarget = new THREE.Vector3( 0, model.geometry.boundingSphere.center.z, 0 );
|
||||
turntable.position.y = model.geometry.boundingBox.min.z-1;
|
||||
scene.add( model );
|
||||
indicator.hide();
|
||||
};
|
||||
|
||||
|
||||
// Lights
|
||||
|
||||
scene.add( new THREE.HemisphereLight( 0x443333, 0x111122 ) );
|
||||
|
||||
addShadowedLight( 1, 1, 1, 0xffffff, 1.35 );
|
||||
addShadowedLight( 0.5, 1, -1, 0xffaa00, 1 );
|
||||
|
||||
// renderer
|
||||
|
||||
renderer = new THREE.WebGLRenderer( { antialias: true } );
|
||||
renderer.setClearColor( scene.fog.color );
|
||||
renderer.setPixelRatio( window.devicePixelRatio );
|
||||
renderer.setSize( container.clientWidth, container.clientWidth*0.6 );
|
||||
|
||||
renderer.gammaInput = true;
|
||||
renderer.gammaOutput = true;
|
||||
|
||||
renderer.shadowMap.enabled = true;
|
||||
renderer.shadowMap.renderReverseSided = false;
|
||||
|
||||
container.appendChild( renderer.domElement );
|
||||
|
||||
// resize
|
||||
|
||||
window.addEventListener( 'resize', onWindowResize, false );
|
||||
|
||||
}
|
||||
function addShadowedLight( x, y, z, color, intensity ) {
|
||||
|
||||
var directionalLight = new THREE.DirectionalLight( color, intensity );
|
||||
directionalLight.position.set( x, y, z );
|
||||
scene.add( directionalLight );
|
||||
|
||||
directionalLight.castShadow = true;
|
||||
|
||||
var d = 1;
|
||||
directionalLight.shadow.camera.left = -d;
|
||||
directionalLight.shadow.camera.right = d;
|
||||
directionalLight.shadow.camera.top = d;
|
||||
directionalLight.shadow.camera.bottom = -d;
|
||||
|
||||
directionalLight.shadow.camera.near = 1;
|
||||
directionalLight.shadow.camera.far = 4;
|
||||
|
||||
directionalLight.shadow.mapSize.width = 1024;
|
||||
directionalLight.shadow.mapSize.height = 1024;
|
||||
|
||||
directionalLight.shadow.bias = -0.005;
|
||||
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
|
||||
camera.aspect = container.clientWidth / (container.clientWidth*0.6) ;
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
renderer.setSize( container.clientWidth, container.clientWidth*0.6 );
|
||||
|
||||
}
|
||||
|
||||
function animate() {
|
||||
|
||||
requestAnimationFrame( animate );
|
||||
|
||||
render();
|
||||
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
||||
var timer = Date.now() * 0.0005;
|
||||
|
||||
camera.position.x = Math.sin( timer ) * cameraDistance;
|
||||
camera.position.z = Math.cos( timer ) * cameraDistance;
|
||||
|
||||
camera.lookAt( cameraTarget );
|
||||
|
||||
renderer.render( scene, camera );
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('duck-example').onclick=function() {
|
||||
indicator.show();
|
||||
loader.load( '../examples/duck/duck_pointcloud.ply', loadGeometry);
|
||||
};
|
||||
document.getElementById('bear-example').onclick=function() {
|
||||
indicator.show();
|
||||
loader.load( '../examples/bear/bear_pointcloud.ply', loadGeometry);
|
||||
};
|
||||
document.getElementById('glue-stick-example').onclick=function() {
|
||||
indicator.show();
|
||||
loader.load( '../examples/glue_stick/glue_stick_pointcloud.ply', loadGeometry);
|
||||
};
|
||||
document.getElementById('sculpture-example').onclick=function() {
|
||||
indicator.show();
|
||||
loader.load( '../examples/sculpture/sculpture_pointcloud.ply', loadGeometry);
|
||||
};
|
||||
document.getElementById('seal-example').onclick=function() {
|
||||
indicator.show();
|
||||
loader.load( '../examples/seal/seal_pointcloud.ply', loadGeometry);
|
||||
};
|
||||
|
||||
loader.load( '../examples/duck/duck_pointcloud.ply', loadGeometry);
|
||||
|
||||
</script>
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
#Slack
|
||||
Use the FabScan Slack channel for direct messaging and chat communication.
|
||||
This is the fastest way of getting support. For joining write an email to
|
||||
info@fabscan.org with subject "add me to slack"
|
||||
This is the fastest way of getting support.
|
||||
|
||||
Signup here: [https://fabscan.signup.team](https://fabscan.signup.team)
|
||||
|
||||
Or write an email to:
|
||||
info@fabscan.org with subject "add me to slack"
|
||||
|
||||
#Google Group
|
||||
For general problems and information use the FabScan google group.
|
||||
|
|
|
|||
|
|
@ -67,3 +67,83 @@ img[alt=drawing_450] {
|
|||
img[alt=browser_logo] {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
ul.example-preview {
|
||||
}
|
||||
|
||||
ul.example-preview > li {
|
||||
width:20%;
|
||||
margin-left: 0 !important;
|
||||
padding-left: 0 !important;
|
||||
list-style: none !important;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#WebGL-output {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#loading-indicator {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
top: 40%;
|
||||
}
|
||||
|
||||
.sk-three-bounce {
|
||||
margin: 5px auto;
|
||||
text-align: center;
|
||||
border: 0.2em white;
|
||||
display: inline-block;
|
||||
background: white;
|
||||
padding: 1em 2em;
|
||||
border-radius: 0.6em;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.sk-three-bounce .sk-child {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #333;
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
-webkit-animation: sk-three-bounce 1.4s ease-in-out 0s infinite both;
|
||||
animation: sk-three-bounce 1.4s ease-in-out 0s infinite both;
|
||||
}
|
||||
|
||||
.sk-three-bounce .sk-bounce1 {
|
||||
-webkit-animation-delay: -0.32s;
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.sk-three-bounce .sk-bounce2 {
|
||||
-webkit-animation-delay: -0.16s;
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-three-bounce {
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-three-bounce {
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}}
|
||||
|
||||
.spacer{
|
||||
padding:10px;
|
||||
}
|
||||
|
|
|
|||
4
docs/css/font-awesome.min.css
vendored
Normal file
4
docs/examples.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
### Examples
|
||||
Here are some examples of scans created with FabScanPi.
|
||||
|
||||
Additionally you can find the examples together with derived meshes as .STL files at [Github](https://github.com/mariolukas/FabScanPi-Server/tree/master/docs/examples).
|
||||
19
docs/examples/README.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# FabScan PI - Sample Scans
|
||||
|
||||
This folder contains some sample scans made with the FabScan Pi.
|
||||
|
||||

|
||||
duck - the famous fabscan rubber duck
|
||||
|
||||

|
||||
bear - the famous fabscan bear
|
||||
|
||||

|
||||
seal - a rubber seal toy
|
||||
|
||||

|
||||
glue_stick - a red glue stick, typically used for 3D printing
|
||||
|
||||

|
||||
sculpture - a sculpture head which was made of plaster
|
||||
|
||||
BIN
docs/examples/bear/bear.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
docs/examples/bear/bear_icon.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
docs/examples/bear/bear_meshed.ply
Normal file
205434
docs/examples/bear/bear_pointcloud.ply
Normal file
BIN
docs/examples/bear/bear_simple.stl
Normal file
BIN
docs/examples/duck/duck.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
docs/examples/duck/duck_icon.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
docs/examples/duck/duck_meshed.ply
Normal file
BIN
docs/examples/duck/duck_pointcloud.ply
Normal file
BIN
docs/examples/duck/duck_simple.stl
Normal file
BIN
docs/examples/glue_stick/glue_stick.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
docs/examples/glue_stick/glue_stick_icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/examples/glue_stick/glue_stick_pointcloud.ply
Normal file
BIN
docs/examples/sculpture/sculpture.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
docs/examples/sculpture/sculpture_icon.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/examples/sculpture/sculpture_pointcloud.ply
Normal file
BIN
docs/examples/seal/seal.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
docs/examples/seal/seal_icon.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/examples/seal/seal_meshed.ply
Normal file
BIN
docs/examples/seal/seal_pointcloud.ply
Normal file
BIN
docs/examples/seal/seal_simple.stl
Normal file
150
docs/hardware.md
|
|
@ -24,6 +24,8 @@ The laser cut files can be found at [https://github.com/mariolukas/FabScan-Case]
|
|||
|
||||
|
||||
#The FabScanPi HAT
|
||||
**General description**
|
||||
|
||||
The FabScan HAT is basically a combination of an Arduino and the old
|
||||
FabScan Shield for Arduino. It provides all connectors for the hardware
|
||||
parts (like motors, servos, lasers, LED's etc.) Instead of an USB
|
||||
|
|
@ -34,6 +36,7 @@ flashed automatically by the FabscanPi-Server application.
|
|||
|
||||

|
||||
|
||||
<<<<<<< HEAD
|
||||
# How to Asselmble the FabScanPi HAT
|
||||
|
||||
**Materials & Tools**
|
||||
|
|
@ -53,11 +56,126 @@ flashed automatically by the FabscanPi-Server application.
|
|||
Use the side cutter to cut two pieces of 3 pins from the male header, like you on the picture above.
|
||||
|
||||
#Connecting the Stepper Motor
|
||||
=======
|
||||
**How to Assemble the FabScanPi HAT**
|
||||
|
||||
|
||||
* * *
|
||||
<i class="fa fa-info-circle spacer" aria-hidden="true"></i> _About Soldering_
|
||||
|
||||
_If you are soldering for the very fist time, we suggest to read the comic ["Soldering is Easy"](https://mightyohm.com/files/soldercomic/FullSolderComic_EN.pdf) by Mitch Altman (soldering wisdom), Andie Nordgren (comic adaption) and Jeff Keyzer (layout and editing)._
|
||||
* * *
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/DogfNxk277Y" frameborder="0" allowfullscreen></iframe>
|
||||
|
||||
The FabScanPi HAT will be delivered with the main components already assembled. You only need to install the headers and connectors which fit your demand.
|
||||

|
||||
|
||||
Let's start with the female 8-pin headers for the stepper motor controllers. First the two headers which are designated with "Stepper Turn Table". Put one in and flip the pcb to solder the pins on the rear side. Solder one pin first and make sure the header is still in the correct position. A "third hand" tool or a pcb-holder are very helpful for this job.
|
||||
|
||||
|
||||
|
||||
Now you can select between three options
|
||||
|
||||
- **Option A:** Two stepper motor ports for the laser adjustment or
|
||||
|
||||
- **Option B:** Two servo connector ports for the laser adjustment or
|
||||
|
||||
- **Option C:** Two stepper and two servo connector ports for the lasers (additional headers required)
|
||||
|
||||
|
||||
|
||||
**Option A:**
|
||||
|
||||
Use the remaining four 8-pin femal pin headers and install them on the pcb. You can now use the HAT with three stepper motors (1x turn table, 2x laser control)
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
**Option B:**
|
||||
|
||||
Use an electronics wire cutter to cut off two 3-pin male headers from the long male-header. Put them into the pinholes labeled "Servo opt." You can now use the HAT with one stepper motors (1x turn table) and two servos (2x servo opt.).
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
**Option C:**
|
||||
|
||||
If you are unsure about using servos or stepper motors you can install both. Therefore you'll need to buy four 8-pin female headers which are at least 8 mm of height. Install them at the pinholes for the "Stepper Laser 1 and 2". Also cut off two 3-pin male headers from the long male-header. Put them into the pinholes labeled "Servo opt." Now you can use either servo controllers nor the connectors for the servos.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
**Connector for the LED-Ring**
|
||||
|
||||
The next connector is the JST connector for the RPi-RingLight. Make sure the direction is correct. Fix it and solder the three pins on the rear side of the PCB.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
**Connectors for the stepper motors**
|
||||
|
||||
Here you can use the three 4-port screw terminals if your stepper cables have no connector plug.
|
||||
|
||||

|
||||
|
||||
If the stepper motor cables have an 4-pin female connector you can use three 4-pin male headers (to be cutted off from the long header).
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
**Connector for Laser(s) and Laser safety switch**
|
||||
|
||||
The next connector to be installed is the 6-port screw terminal. It must be soldered into the corresponding pin holes between the JST connector and the 8-pin female header for the table stepper. Later this 6-port terminal will be used to connect the Laser(s) and the Laser safety switch.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
**Power Connector** (DC- jack)
|
||||
|
||||
Now the DC-jack power connector will be installed into three oval pin holes across from the 2x20-pin socket header. Soldering is done from the top side of the PCB.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
**Assembling the Raspberry-Pi Connector**
|
||||
|
||||
Now the 2x20-pin socket connector must be installed from the rear side of the PCB (where we only did soldering till now). Soldering of the 2x20-pin connector is done on the front side (where all our parts are placed). This connector is used as interface for the Raspberry-Pi.
|
||||
|
||||

|
||||
|
||||
_Attention: The power connector in this image is soldered in an alternative way. The recommended way
|
||||
is shown in the image before._
|
||||
|
||||
|
||||
|
||||
**Mount the 5V DC/DC converter or 5V external Power Source**
|
||||
|
||||
Additionally to the 12V DC coming from the power supply the FabScanPi needs 5V DC. Now you have to decide if you want to use a DC/DC converter IC which generates the 5V out of the 12V from the external 12 power supply (common solution).
|
||||
|
||||
For the DC/DC converter option you can find further instructions and pictures on the [Watterott electronic website](https://github.com/watterott/RPi-FabScan-HAT/blob/master/hardware/RPi-FabScan-HAT_Assembly.pdf).
|
||||
|
||||
|
||||
|
||||
If you are using another power supply which is capable of delivering 12V and 5V DC you can connect it as well. Details can be found [here](#5V-EXT).
|
||||
|
||||
|
||||
|
||||
#Connecting the Stepper Motor(s)
|
||||
|
||||
>>>>>>> master
|
||||
There are different kinds of stepper motos. Mostly with 4 or 6 leads. For
|
||||
connecting the stepper motor to the FabScanPi HAT you need to know the
|
||||
corresponding lead pairs of the motor coils. The best way to find out something
|
||||
about the motor is to have a look at the datasheet of the motor manufacturer.
|
||||
In the following desciptions the pairs are called (1A, 1B) and (2A, 2B).
|
||||
In the following desciptions the pairs are called (2B, 1B) and (1A, 2A).
|
||||
|
||||

|
||||

|
||||
|
|
@ -130,7 +248,7 @@ for 1 turntable stepper motor, 1 PiCam and 1 laser.
|
|||
| (white square) | Ground (GND) |
|
||||
| 5V | 5V output from regulator to FabScanPi HAT |
|
||||
|
||||
|
||||
For the DC/DC converter option you can find further instructions and pictures on the [Watterott electronic website](https://github.com/watterott/RPi-FabScan-HAT/blob/master/hardware/RPi-FabScan-HAT_Assembly.pdf).
|
||||
|
||||
NOTE: For the final stage of constuction a more powerful power supply is needed. At the moment there are no technical specifications available.
|
||||
|
||||
|
|
@ -144,7 +262,7 @@ NOTE: Make sure you switch on the both power sources at the same time to avoid s
|
|||
|
||||
|
||||
|
||||
**Option C:**
|
||||
**Option C:**<a name="5V-EXT"></a>
|
||||
|
||||
Connect 12V DC to the HAT (round connector) and connect a 5V DC power source to the 5V pin regulator pin on the HAT. Make sure the 5V power source can provide a current of min. 2.0A for
|
||||
|
||||
|
|
@ -178,19 +296,19 @@ Even if you use the srew set from Watterott, as given in the *BOM*, here is the
|
|||
|
||||
**Screws**
|
||||
|
||||
| Type | Length | Qty | Usage |
|
||||
|------|--------|-----|-------------------------|
|
||||
| M2 | 16 | 2 | Servo Hitec-HS53 |
|
||||
| | | 2 | Security Switch |
|
||||
| | | 1 | 5mW line Laser red |
|
||||
| M2.5 | 15 | 4 | RaspberryPi |
|
||||
| M3 | 10 | 4 | Stepper motor |
|
||||
| | | 4 | RPi-RingLight |
|
||||
| | | 4 | Turn-table Mounting Hub |
|
||||
| Type | Length | Qty | Usage |
|
||||
| ---- | ------ | ---- | ----------------------- |
|
||||
| M2 | 16 | 2 | Servo Hitec-HS53 |
|
||||
| | | 2 | Security Switch |
|
||||
| | | 1 | 5mW line Laser red |
|
||||
| M2.5 | 15 | 4 | RaspberryPi |
|
||||
| M3 | 10 | 4 | Stepper motor |
|
||||
| | | 4 | RPi-RingLight |
|
||||
| | | 4 | Turn-table Mounting Hub |
|
||||
|
||||
**Washers**
|
||||
|
||||
| Type | Heigth | Qty | Usage |
|
||||
|---------|--------|-----|---------------|
|
||||
| 3.4/4.5 | 1 | 4 | Stepper motor |
|
||||
| 2.5/4.5 | 3 | 4 | RaspberryPi |
|
||||
| Type | Heigth | Qty | Usage |
|
||||
| ------- | ------ | ---- | ------------- |
|
||||
| 3.4/4.5 | 1 | 4 | Stepper motor |
|
||||
| 2.5/4.5 | 3 | 4 | RaspberryPi |
|
||||
|
|
|
|||
BIN
docs/images/FabScanPi_Calibration_1.jpg
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
docs/images/FabScanPi_Calibration_2.jpg
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
docs/images/FabScanPi_Calibration_3.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
docs/images/FabScanPi_Version_Update.jpg
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/images/RingLicht_1.jpg
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
docs/images/RingLicht_1b.jpg
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
docs/images/RingLicht_2.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
docs/images/RingLicht_3.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
docs/images/RingLicht_4.jpg
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
docs/images/RingLicht_5.jpg
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
docs/images/RingLicht_6.jpg
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 82 KiB |
BIN
docs/images/hat_assembly_1.jpg
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
BIN
docs/images/hat_assembly_2.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
docs/images/hat_assembly_2a.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
docs/images/hat_assembly_2b.jpg
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
docs/images/hat_assembly_3.jpg
Normal file
|
After Width: | Height: | Size: 487 KiB |
BIN
docs/images/hat_assembly_4.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
docs/images/hat_assembly_4a.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
docs/images/hat_assembly_5.jpg
Normal file
|
After Width: | Height: | Size: 624 KiB |
BIN
docs/images/hat_assembly_6.jpg
Normal file
|
After Width: | Height: | Size: 484 KiB |
BIN
docs/images/hat_assembly_7.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
482
docs/js/PLYLoader.js
Executable file
|
|
@ -0,0 +1,482 @@
|
|||
/**
|
||||
* @author Wei Meng / http://about.me/menway
|
||||
*
|
||||
* Description: A THREE loader for PLY ASCII files (known as the Polygon File Format or the Stanford Triangle Format).
|
||||
*
|
||||
*
|
||||
* Limitations: ASCII decoding assumes file is UTF-8.
|
||||
*
|
||||
* Usage:
|
||||
* var loader = new THREE.PLYLoader();
|
||||
* loader.load('./models/ply/ascii/dolphins.ply', function (geometry) {
|
||||
*
|
||||
* scene.add( new THREE.Mesh( geometry ) );
|
||||
*
|
||||
* } );
|
||||
*
|
||||
* If the PLY file uses non standard property names, they can be mapped while
|
||||
* loading. For example, the following maps the properties
|
||||
* “diffuse_(red|green|blue)” in the file to standard color names.
|
||||
*
|
||||
* loader.setPropertyNameMapping( {
|
||||
* diffuse_red: 'red',
|
||||
* diffuse_green: 'green',
|
||||
* diffuse_blue: 'blue'
|
||||
* } );
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
THREE.PLYLoader = function () {
|
||||
|
||||
this.propertyNameMapping = {};
|
||||
|
||||
};
|
||||
|
||||
THREE.PLYLoader.prototype = {
|
||||
|
||||
constructor: THREE.PLYLoader,
|
||||
|
||||
setPropertyNameMapping: function ( mapping ) {
|
||||
|
||||
this.propertyNameMapping = mapping;
|
||||
|
||||
},
|
||||
|
||||
load: function ( url, callback ) {
|
||||
|
||||
var scope = this;
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
request.addEventListener( 'load', function ( event ) {
|
||||
|
||||
var geometry = scope.parse( event.target.response );
|
||||
|
||||
scope.dispatchEvent( { type: 'load', content: geometry } );
|
||||
|
||||
if ( callback ) callback( geometry );
|
||||
|
||||
}, false );
|
||||
|
||||
request.addEventListener( 'progress', function ( event ) {
|
||||
|
||||
scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
|
||||
|
||||
}, false );
|
||||
|
||||
request.addEventListener( 'error', function () {
|
||||
|
||||
scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
|
||||
|
||||
}, false );
|
||||
|
||||
request.open( 'GET', url, true );
|
||||
request.responseType = "arraybuffer";
|
||||
request.send( null );
|
||||
|
||||
},
|
||||
|
||||
bin2str: function (buf) {
|
||||
|
||||
var array_buffer = new Uint8Array(buf);
|
||||
var str = '';
|
||||
for (var i = 0; i < buf.byteLength; i ++) {
|
||||
str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
},
|
||||
|
||||
isASCII: function( data ) {
|
||||
|
||||
var header = this.parseHeader( this.bin2str( data ) );
|
||||
|
||||
return header.format === "ascii";
|
||||
|
||||
},
|
||||
|
||||
parse: function ( data ) {
|
||||
|
||||
if ( data instanceof ArrayBuffer ) {
|
||||
|
||||
return this.isASCII( data )
|
||||
? this.parseASCII( this.bin2str( data ) )
|
||||
: this.parseBinary( data );
|
||||
|
||||
} else {
|
||||
|
||||
return this.parseASCII( data );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
parseHeader: function ( data ) {
|
||||
|
||||
var patternHeader = /ply([\s\S]*)end_header\s/;
|
||||
var headerText = "";
|
||||
var headerLength = 0;
|
||||
var result = patternHeader.exec( data );
|
||||
if ( result !== null ) {
|
||||
headerText = result [ 1 ];
|
||||
headerLength = result[ 0 ].length;
|
||||
}
|
||||
|
||||
var header = {
|
||||
comments: [],
|
||||
elements: [],
|
||||
headerLength: headerLength
|
||||
};
|
||||
|
||||
var lines = headerText.split( '\n' );
|
||||
var currentElement = undefined;
|
||||
var lineType, lineValues;
|
||||
|
||||
function make_ply_element_property( propertValues, propertyNameMapping ) {
|
||||
|
||||
var property = {
|
||||
type: propertValues[ 0 ]
|
||||
};
|
||||
|
||||
if ( property.type === 'list' ) {
|
||||
|
||||
property.name = propertValues[ 3 ];
|
||||
property.countType = propertValues[ 1 ];
|
||||
property.itemType = propertValues[ 2 ];
|
||||
|
||||
} else {
|
||||
|
||||
property.name = propertValues[ 1 ];
|
||||
|
||||
}
|
||||
|
||||
if ( property.name in propertyNameMapping ) {
|
||||
|
||||
property.name = propertyNameMapping[ property.name ];
|
||||
|
||||
}
|
||||
|
||||
return property;
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0; i < lines.length; i ++ ) {
|
||||
|
||||
var line = lines[ i ];
|
||||
line = line.trim()
|
||||
if ( line === "" ) { continue; }
|
||||
lineValues = line.split( /\s+/ );
|
||||
lineType = lineValues.shift()
|
||||
line = lineValues.join(" ")
|
||||
|
||||
switch ( lineType ) {
|
||||
|
||||
case "format":
|
||||
|
||||
header.format = lineValues[0];
|
||||
header.version = lineValues[1];
|
||||
|
||||
break;
|
||||
|
||||
case "comment":
|
||||
|
||||
header.comments.push(line);
|
||||
|
||||
break;
|
||||
|
||||
case "element":
|
||||
|
||||
if ( !(currentElement === undefined) ) {
|
||||
|
||||
header.elements.push(currentElement);
|
||||
|
||||
}
|
||||
|
||||
currentElement = Object();
|
||||
currentElement.name = lineValues[0];
|
||||
currentElement.count = parseInt( lineValues[1] );
|
||||
currentElement.properties = [];
|
||||
|
||||
break;
|
||||
|
||||
case "property":
|
||||
|
||||
currentElement.properties.push( make_ply_element_property( lineValues, this.propertyNameMapping ) );
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
console.log("unhandled", lineType, lineValues);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !(currentElement === undefined) ) {
|
||||
|
||||
header.elements.push(currentElement);
|
||||
|
||||
}
|
||||
|
||||
return header;
|
||||
|
||||
},
|
||||
|
||||
parseASCIINumber: function ( n, type ) {
|
||||
|
||||
switch ( type ) {
|
||||
|
||||
case 'char': case 'uchar': case 'short': case 'ushort': case 'int': case 'uint':
|
||||
case 'int8': case 'uint8': case 'int16': case 'uint16': case 'int32': case 'uint32':
|
||||
|
||||
return parseInt( n );
|
||||
|
||||
case 'float': case 'double': case 'float32': case 'float64':
|
||||
|
||||
return parseFloat( n );
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
parseASCIIElement: function ( properties, line ) {
|
||||
|
||||
var values = line.split( /\s+/ );
|
||||
|
||||
var element = Object();
|
||||
|
||||
for ( var i = 0; i < properties.length; i ++ ) {
|
||||
|
||||
if ( properties[i].type === "list" ) {
|
||||
|
||||
var list = [];
|
||||
var n = this.parseASCIINumber( values.shift(), properties[i].countType );
|
||||
|
||||
for ( var j = 0; j < n; j ++ ) {
|
||||
|
||||
list.push( this.parseASCIINumber( values.shift(), properties[i].itemType ) );
|
||||
|
||||
}
|
||||
|
||||
element[ properties[i].name ] = list;
|
||||
|
||||
} else {
|
||||
|
||||
element[ properties[i].name ] = this.parseASCIINumber( values.shift(), properties[i].type );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return element;
|
||||
|
||||
},
|
||||
|
||||
parseASCII: function ( data ) {
|
||||
|
||||
// PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var result;
|
||||
|
||||
var header = this.parseHeader( data );
|
||||
|
||||
var patternBody = /end_header\s([\s\S]*)$/;
|
||||
var body = "";
|
||||
if ( ( result = patternBody.exec( data ) ) !== null ) {
|
||||
body = result [ 1 ];
|
||||
}
|
||||
|
||||
var lines = body.split( '\n' );
|
||||
var currentElement = 0;
|
||||
var currentElementCount = 0;
|
||||
geometry.useColor = true;
|
||||
|
||||
for ( var i = 0; i < lines.length; i ++ ) {
|
||||
|
||||
var line = lines[ i ];
|
||||
line = line.trim()
|
||||
if ( line === "" ) { continue; }
|
||||
|
||||
if ( currentElementCount >= header.elements[currentElement].count ) {
|
||||
|
||||
currentElement ++;
|
||||
currentElementCount = 0;
|
||||
|
||||
}
|
||||
|
||||
var element = this.parseASCIIElement( header.elements[currentElement].properties, line );
|
||||
|
||||
this.handleElement( geometry, header.elements[currentElement].name, element );
|
||||
|
||||
currentElementCount ++;
|
||||
|
||||
}
|
||||
|
||||
return this.postProcess( geometry );
|
||||
|
||||
},
|
||||
|
||||
postProcess: function ( geometry ) {
|
||||
|
||||
if ( geometry.useColor ) {
|
||||
|
||||
for ( var i = 0; i < geometry.faces.length; i ++ ) {
|
||||
|
||||
geometry.faces[i].vertexColors = [
|
||||
geometry.colors[geometry.faces[i].a],
|
||||
geometry.colors[geometry.faces[i].b],
|
||||
geometry.colors[geometry.faces[i].c]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
geometry.elementsNeedUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
geometry.computeBoundingSphere();
|
||||
|
||||
return geometry;
|
||||
|
||||
},
|
||||
|
||||
handleElement: function ( geometry, elementName, element ) {
|
||||
|
||||
if ( elementName === "vertex" ) {
|
||||
|
||||
geometry.vertices.push(
|
||||
new THREE.Vector3( element.x, element.y, element.z )
|
||||
);
|
||||
|
||||
if ( 'red' in element && 'green' in element && 'blue' in element ) {
|
||||
|
||||
geometry.useColor = true;
|
||||
|
||||
var color = new THREE.Color();
|
||||
color.setRGB( element.red / 255.0, element.green / 255.0, element.blue / 255.0 );
|
||||
geometry.colors.push( color );
|
||||
|
||||
}
|
||||
|
||||
} else if ( elementName === "face" ) {
|
||||
|
||||
var vertex_indices = element.vertex_indices;
|
||||
|
||||
if ( vertex_indices.length === 3 ) {
|
||||
|
||||
geometry.faces.push(
|
||||
new THREE.Face3( vertex_indices[ 0 ], vertex_indices[ 1 ], vertex_indices[ 2 ] )
|
||||
);
|
||||
|
||||
} else if ( vertex_indices.length === 4 ) {
|
||||
|
||||
geometry.faces.push(
|
||||
new THREE.Face3( vertex_indices[ 0 ], vertex_indices[ 1 ], vertex_indices[ 3 ] ),
|
||||
new THREE.Face3( vertex_indices[ 1 ], vertex_indices[ 2 ], vertex_indices[ 3 ] )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
binaryRead: function ( dataview, at, type, little_endian ) {
|
||||
|
||||
switch ( type ) {
|
||||
|
||||
// corespondences for non-specific length types here match rply:
|
||||
case 'int8': case 'char': return [ dataview.getInt8( at ), 1 ];
|
||||
|
||||
case 'uint8': case 'uchar': return [ dataview.getUint8( at ), 1 ];
|
||||
|
||||
case 'int16': case 'short': return [ dataview.getInt16( at, little_endian ), 2 ];
|
||||
|
||||
case 'uint16': case 'ushort': return [ dataview.getUint16( at, little_endian ), 2 ];
|
||||
|
||||
case 'int32': case 'int': return [ dataview.getInt32( at, little_endian ), 4 ];
|
||||
|
||||
case 'uint32': case 'uint': return [ dataview.getUint32( at, little_endian ), 4 ];
|
||||
|
||||
case 'float32': case 'float': return [ dataview.getFloat32( at, little_endian ), 4 ];
|
||||
|
||||
case 'float64': case 'double': return [ dataview.getFloat64( at, little_endian ), 8 ];
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
binaryReadElement: function ( dataview, at, properties, little_endian ) {
|
||||
|
||||
var element = Object();
|
||||
var result, read = 0;
|
||||
|
||||
for ( var i = 0; i < properties.length; i ++ ) {
|
||||
|
||||
if ( properties[i].type === "list" ) {
|
||||
|
||||
var list = [];
|
||||
|
||||
result = this.binaryRead( dataview, at + read, properties[i].countType, little_endian );
|
||||
var n = result[0];
|
||||
read += result[1];
|
||||
|
||||
for ( var j = 0; j < n; j ++ ) {
|
||||
|
||||
result = this.binaryRead( dataview, at + read, properties[i].itemType, little_endian );
|
||||
list.push( result[0] );
|
||||
read += result[1];
|
||||
|
||||
}
|
||||
|
||||
element[ properties[i].name ] = list;
|
||||
|
||||
} else {
|
||||
|
||||
result = this.binaryRead( dataview, at + read, properties[i].type, little_endian );
|
||||
element[ properties[i].name ] = result[0];
|
||||
read += result[1];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [ element, read ];
|
||||
|
||||
},
|
||||
|
||||
parseBinary: function ( data ) {
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
var header = this.parseHeader( this.bin2str( data ) );
|
||||
var little_endian = (header.format === "binary_little_endian");
|
||||
var body = new DataView( data, header.headerLength );
|
||||
var result, loc = 0;
|
||||
|
||||
for ( var currentElement = 0; currentElement < header.elements.length; currentElement ++ ) {
|
||||
|
||||
for ( var currentElementCount = 0; currentElementCount < header.elements[currentElement].count; currentElementCount ++ ) {
|
||||
|
||||
result = this.binaryReadElement( body, loc, header.elements[currentElement].properties, little_endian );
|
||||
loc += result[1];
|
||||
var element = result[0];
|
||||
|
||||
this.handleElement( geometry, header.elements[currentElement].name, element );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this.postProcess( geometry );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
THREE.EventDispatcher.prototype.apply( THREE.PLYLoader.prototype );
|
||||
40560
docs/js/three.js
Executable file
32
docs/news.md
|
|
@ -1,3 +1,4 @@
|
|||
<<<<<<< HEAD
|
||||
### New FabScanPi release with auto calibration (2017-02-01)
|
||||
A new release of the FabScanPi software with some new exciting features:
|
||||
|
||||
|
|
@ -16,5 +17,36 @@ We uploaded some FabScan example scans. You can explore them by visiting the exa
|
|||
### FabScanPi goes slack (2016-07-10)
|
||||
To improve the communication between FabScanPi users and enhance the support FabScanPi now uses slack. Register at
|
||||
[https://fabscan.slack.com](https://fabscan.slack.com) and join the FabScanPi community.
|
||||
=======
|
||||
[comment]: <> (### New FabScanPi release with auto calibration (2017-02-01)
|
||||
[comment]: <> (A new release of the FabScanPi software with some new exciting features:)
|
||||
[comment]: <> ()
|
||||
[comment]: <> ( * Auto-calibration improves the scan results and simplifies the setup process.)
|
||||
[comment]: <> ( * Read news from the FabScanPi project to stay informed about new features and improvements.)
|
||||
[comment]: <> ( * Improved updates allow to update your installation with one click.)
|
||||
[comment]: <> ()
|
||||
[comment]: <> (Have fun!)
|
||||
|
||||
**First FabScanPi Workshop (2017-03-30)**
|
||||
|
||||
On 1th of april 2017 we will provide the first FabScanPi workshop.
|
||||
It will take place at Watterott electronic? . The workshop will include all the
|
||||
needed parts to build your own FabScanPi. You will be guided during the whole workshop.
|
||||
And finally you will get a sneak preview to the nex release of the FabScanPi
|
||||
software which includes autocalibration!
|
||||
|
||||
More information can be found at: https://goo.gl/mC9cHs
|
||||
|
||||
**Added some example scans (2017-01-31)**
|
||||
|
||||
We uploaded some FabScan example scans. You can explore them by visiting the example page.
|
||||
[http://mariolukas.github.io/FabScanPi-Server/examples/](http://mariolukas.github.io/FabScanPi-Server/examples/)
|
||||
|
||||
|
||||
**FabScanPi goes slack (2016-07-10)**
|
||||
|
||||
To improve the communication between FabScanPi users and enhance the support FabScanPi now uses slack. Register at
|
||||
[https://fabscan.signup.team](https://fabscan.signup.team) and join the FabScanPi community.
|
||||
>>>>>>> master
|
||||
|
||||
We look forward to welcoming you!
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ extra_javascript:
|
|||
theme: readthedocs
|
||||
theme_dir: docs-theme
|
||||
extra:
|
||||
version: 1.0
|
||||
version: 0.4.0
|
||||
repo_url: https://github.com/mariolukas/FabScanPi-Server
|
||||
site_author: Mario Lukas
|
||||
site_favicon: images/fabscanpi_ICON.png
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@ pillow ==2.7
|
|||
Pykka >=1.2
|
||||
numpy >=1.9
|
||||
semver >=2.0
|
||||
mock
|
||||
mock
|
||||
1
setup.py
|
|
@ -125,4 +125,3 @@ def params():
|
|||
return locals()
|
||||
|
||||
setup(**params())
|
||||
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ class FSScanner(threading.Thread):
|
|||
"upgrade": {
|
||||
"available": self._upgrade_available,
|
||||
"version": self._upgrade_version
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import logging
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FSScannerFactory(object):
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -387,4 +387,4 @@ class ImageProcessor(ImageProcessorInterface):
|
|||
|
||||
if ret:
|
||||
cv2.cornerSubPix(gray, corners, (11,11), (-1, -1), self._criteria)
|
||||
return corners
|
||||
return corners
|
||||
|
|
@ -3,7 +3,11 @@ from urllib2 import URLError
|
|||
|
||||
from mock import patch
|
||||
|
||||
<<<<<<< HEAD
|
||||
from fabscan.util.FSUpdate import get_latest_version_tag, upgrade_is_available, do_upgrade
|
||||
=======
|
||||
from fabscan.util.FSUpdate import get_latest_version_tag, upgrade_is_available
|
||||
>>>>>>> master
|
||||
|
||||
|
||||
class FSUpdateTestCase(unittest.TestCase):
|
||||
|
|
@ -30,11 +34,14 @@ class FSUpdateTestCase(unittest.TestCase):
|
|||
self.assertFalse(upgrade_available)
|
||||
self.assertEqual(upgrade_version, "0.3.1")
|
||||
|
||||
<<<<<<< HEAD
|
||||
@patch('os.system')
|
||||
def test_do_upgrade(self, system_mock):
|
||||
do_upgrade()
|
||||
system_mock.assert_called_once_with('nohup bash -c "sudo apt-get update && sudo apt-get dist-upgrade" > /var/log/fabscanpi/upgrade.log')
|
||||
|
||||
=======
|
||||
>>>>>>> master
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
|||