stl_stats
Posted by admin in 3D Printer on July 26th, 2014
This is a small C++ program to iterate over a STL file and to print out a few things:
- Max/Min for X, Y and Z –> Bounding Box
- Number of layers
- “Useful” layers : given a minimum height, if some layers on Z axis are too small it performs a merge. Loosely speaking, if the ratio between “useful” layers and real layers of the model is too low, it means that the printing of this given model can potentially be not nice in between some layers (it is a sampling issue).
- Example of problematic details on the bottom of Darth Vader Pen Cup:
NB: For reading the STL file, it is a simple copy-paste from the really good OpenSCAD.
Usage:
stl_stats filename.stl [minLayerHeight]
Dependencies:
boost_regex and boost_system
Output examples:
./stl_stats ../../../Téléchargements/20mm-box.stl
BinarySTL = 0
Layer 0: Axis Z 0
Layer 1: Axis Z 10
—> New Layer height = 10
Number of layers 2
Useful layers 1 (small bug actually it is 2)
Face Number = 12
XMin = -10 XMax = 10, Distance = 20
YMin = -10 YMax = 10, Distance = 20
ZMin = 0 ZMax = 10, Distance = 10
Minimum layer height = 0.3
Max number of layers = 33.3333
./stl_stats ../../../Téléchargements/darth_vader_pen_cup.stl
Layer 1142: Axis Z 80.001
Previous layer too thin, useless
Number of layers 1143
Useful layers 115
Face Number = 5406
XMin = -36.001 XMax = 54, Distance = 90.001
YMin = -49 YMax = 41.001, Distance = 90.001
ZMin = -0.001 ZMax = 80.001, Distance = 80.002
Minimum layer height = 0.3
Max number of layers = 266.673
./stl_stats ../../../Téléchargements/darth_vader_pen_cup.stl 0.1
Layer 1142: Axis Z 80.001
Previous layer too thin, useless
Number of layers 1143
Useful layers 214
Face Number = 5406
XMin = -36.001 XMax = 54, Distance = 90.001
YMin = -49 YMax = 41.001, Distance = 90.001
ZMin = -0.001 ZMax = 80.001, Distance = 80.002
Minimum layer height = 0.1
Max number of layers = 800.02
Source code:
#include <iostream> #include <fstream> #include <sstream> #include <boost/algorithm/string.hpp> #include <boost/regex.hpp> #include <boost/lexical_cast.hpp> #include <boost/filesystem.hpp> namespace fs = boost::filesystem; #include <boost/assign/std/vector.hpp> using namespace boost::assign; // bring 'operator+=()' into scope #include <boost/detail/endian.hpp> #include <boost/cstdint.hpp> #include <map> //CODE COMING FROM OPENSCAD #define STL_FACET_NUMBYTES 4*3*4+2 // as there is no 'float32_t' standard, we assume the systems 'float' // is a 'binary32' aka 'single' standard IEEE 32-bit floating point type union stl_facet { uint8_t data8[ STL_FACET_NUMBYTES ]; uint32_t data32[4*3]; struct facet_data { float i, j, k; float x1, y1, z1; float x2, y2, z2; float x3, y3, z3; uint16_t attribute_byte_count; } data; }; inline void uint32_byte_swap( uint32_t &x ) { #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 x = __builtin_bswap32( x ); #elif defined(__clang__) x = __builtin_bswap32( x ); #elif defined(_MSC_VER) x = _byteswap_ulong( x ); #else uint32_t b1 = ( 0x000000FF & x ) << 24; uint32_t b2 = ( 0x0000FF00 & x ) << 8; uint32_t b3 = ( 0x00FF0000 & x ) >> 8; uint32_t b4 = ( 0xFF000000 & x ) >> 24; x = b1 | b2 | b3 | b4; #endif } inline void read_stl_facet( std::ifstream &f, stl_facet &facet ) { f.read( (char*)facet.data8, STL_FACET_NUMBYTES ); #ifdef BOOST_BIG_ENDIAN for ( int i = 0; i < 12; i++ ) { uint32_byte_swap( facet.data32[ i ] ); } // we ignore attribute byte count #endif } inline int readStlFile(const char *filename, double minLayerHeight = 0.3 ) { // Open file and position at the end std::ifstream f(filename, std::ios::in | std::ios::binary | std::ios::ate); if (!f.good()) { std::cerr << "WARNING: Can't open stl file:" << filename << std::endl; return -1; } boost::regex ex_sfe("solid|facet|endloop"); boost::regex ex_outer("outer loop"); boost::regex ex_vertex("vertex"); boost::regex ex_vertices("\\s*vertex\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)"); bool binary = false; std::streampos file_size = f.tellg(); f.seekg(80); uint32_t facenum = 0; if (f.good() && !f.eof()) { f.read((char *)&facenum, sizeof(uint32_t)); #ifdef BOOST_BIG_ENDIAN uint32_byte_swap( facenum ); #endif if (file_size == static_cast<std::streamoff>(80 + 4 + 50*facenum)) { binary = true; } } f.seekg(0); //START OF MY STAT STUFF std::cout << "BinarySTL = " << binary << std::endl; double XMin = 1000000000.0, XMax = -10000000000.0; double YMin = 1000000000.0, YMax = -10000000000.0; double ZMin = 1000000000.0, ZMax = -10000000000.0; facenum = 0; std::map<double, uint32_t> stlLayers; //number of layers //END OF MY STAT STUFF char data[5]; f.read(data, 5); if (!binary && !f.eof() && f.good() && !memcmp(data, "solid", 5)) { int i = 0; double vdata[3][3]; std::string line; std::getline(f, line); while (!f.eof()) { std::getline(f, line); boost::trim(line); if (boost::regex_search(line, ex_sfe)) { continue; } if (boost::regex_search(line, ex_outer)) { i = 0; continue; } boost::smatch results; if (boost::regex_search(line, results, ex_vertices)) { try { for (int v=0;v<3;v++) { vdata[i][v] = boost::lexical_cast<double>(results[v+1]); } } catch (const boost::bad_lexical_cast &blc) { std::cout << "WARNING: Can't parse vertex line:" << line; i = 10; continue; } if (++i == 3) { //CREATE TRIANGLE /* p->append_poly(); p->append_vertex(vdata[0][0], vdata[0][1], vdata[0][2]); p->append_vertex(vdata[1][0], vdata[1][1], vdata[1][2]); p->append_vertex(vdata[2][0], vdata[2][1], vdata[2][2]); */ facenum++; //min,max for(unsigned j = 0 ; j < 3 ; j ++ ) { if ( XMin > vdata[j][0] ) { XMin = vdata[j][0]; } if ( XMax < vdata[j][0] ) { XMax = vdata[j][0]; } if ( YMin > vdata[j][1] ) { YMin = vdata[j][1]; } if ( YMax < vdata[j][1] ) { YMax = vdata[j][1]; } if ( ZMin > vdata[j][2] ) { ZMin = vdata[j][2]; } if ( ZMax < vdata[j][2] ) { ZMax = vdata[j][2]; } } //stl layers for(unsigned j = 0 ; j < 3 ; j ++ ) { stlLayers[ vdata[j][2] ] = 1; } } } } } else if (binary && !f.eof() && f.good()) { f.ignore(80-5+4); while (1) { stl_facet facet; read_stl_facet( f, facet ); if (f.eof()) break; //CREATE TRIANGLE facenum++; // p->append_poly(); // p->append_vertex(facet.data.x1, facet.data.y1, facet.data.z1); // p->append_vertex(facet.data.x2, facet.data.y2, facet.data.z2); // p->append_vertex(facet.data.x3, facet.data.y3, facet.data.z3); //min,max if ( XMin > facet.data.x1 ) { XMin = facet.data.x1; } if ( XMin > facet.data.x2 ) { XMin = facet.data.x2; } if ( XMin > facet.data.x3 ) { XMin = facet.data.x3; } if ( XMax < facet.data.x1 ) { XMax = facet.data.x1; } if ( XMax < facet.data.x2 ) { XMax = facet.data.x2; } if ( XMax < facet.data.x3 ) { XMax = facet.data.x3; } if ( YMin > facet.data.y1 ) { YMin = facet.data.y1; } if ( YMin > facet.data.y2 ) { YMin = facet.data.y2; } if ( YMin > facet.data.y3 ) { YMin = facet.data.y3; } if ( YMax < facet.data.y1 ) { YMax = facet.data.y1; } if ( YMax < facet.data.y2 ) { YMax = facet.data.y2; } if ( YMax < facet.data.y3 ) { YMax = facet.data.y3; } if ( ZMin > facet.data.z1 ) { ZMin = facet.data.z1; } if ( ZMin > facet.data.z2 ) { ZMin = facet.data.z2; } if ( ZMin > facet.data.z3 ) { ZMin = facet.data.z3; } if ( ZMax < facet.data.z1 ) { ZMax = facet.data.z1; } if ( ZMax < facet.data.z2 ) { ZMax = facet.data.z2; } if ( ZMax < facet.data.z3 ) { ZMax = facet.data.z3; } //stl layers stlLayers[ facet.data.z1 ] = 1; stlLayers[ facet.data.z2 ] = 1; stlLayers[ facet.data.z3 ] = 1; } } std::map<double, uint32_t>::iterator stlLayer_it; uint32_t layers = 0, usefulLayers = 0; double previousLayer = -10000000.0; for( std::map<double, uint32_t>::iterator it = stlLayers.begin(); it != stlLayers.end(); ++ it ) { std::cout << "Layer " << layers << ": Axis Z " << it->first << std::endl; if ( layers > 0 ) { if ( minLayerHeight > (it->first - previousLayer) ) { std::cout << "Previous layer too thin, useless" << std::endl; } else { usefulLayers++; std::cout << " ---> New Layer height = " << (it->first - previousLayer) << std::endl; previousLayer = it->first; } } else { previousLayer = it->first; } layers ++; } std::cout << "Number of layers " << layers << std::endl; std::cout << "Useful layers " << usefulLayers << std::endl; std::cout << "Face Number = " << facenum << std::endl; std::cout << "XMin = " << XMin << " XMax = " << XMax << ", Distance = " << (XMax - XMin) << std::endl; std::cout << "YMin = " << YMin << " YMax = " << YMax << ", Distance = " << (YMax - YMin) << std::endl; std::cout << "ZMin = " << ZMin << " ZMax = " << ZMax << ", Distance = " << (ZMax - ZMin) << std::endl; std::cout << "Minimum layer height = " << minLayerHeight << std::endl; std::cout << "Max number of layers = " << ((ZMax - ZMin)/minLayerHeight) << std::endl; return 0; } static int usage() { std::cout << "stl_stats filename.stl [minLayerHeight]" << std::endl; return -1; } int main(int argc, char **argv) { if ( argc < 2 || argc > 3 ) { return usage(); } const char *filename = argv[1]; double minLayerHeight = 0.3; if ( argc == 3 ) { minLayerHeight = atof(argv[2]); } return readStlFile(filename,minLayerHeight); }
syntax highlighted by Code2HTML, v. 0.9.1
Velleman K8200 – Rigidifier le haut du support de la vis pour Z
Posted by admin in 3D Printer on July 26th, 2014
Il y a cette superbe pièce à imprimer directement sur thingiverse (http://www.thingiverse.com/thing:166023), quand on voit la pièce d’origine on comprend
Résultat: Amélioration de l’impression au niveau des couches, elles sont un peu moins visibles.
Par contre le support du Z au niveau du moteur pas à pas çà bouge …. mais bon c’est pas nouveau
Velleman K8200 – Ventilateur horizontal et tole d’isolation
Posted by admin in 3D Printer on July 26th, 2014
Je trouve que le montage d’origine est complètement nul, il y a une légion de “guides” pour ce ventilo sur thingiverse.
La version 0.0
A cause de ma précédente mésaventure sur l’extrudeur, çà s’est en fait transformé en opportunité. La tôle que j’ai utilisé est assez grande pour faire aussi office de support pour le ventilateur.
Je ne m’en suis pas privé et j’ai mis directement le ventilateur à souffler horizontalement.
Résultat: la qualité des impressions a bien augmenté très nettement.
Par contre, j’ai vu qu’il y avait beaucoup de variations de température au niveau de la buse.
La version 0.1
Pour contrer les grosses variations de température, j’avais encore un bout de tôle fine.
Ben oui, du coup je l’ai formé grossièrement afin de faire un guide qui n’envoie pas d’air sur la tête.
Résultat: la qualité des impressions a augmenté légèrement et surtout il y a que très peu de variations de température au niveau de la buse.
Fedora Core 20 SSD/HD Migration
Prerequisites
- Put the SSD/HD in your system (can be Sata or USB through a case with adaptor)
- Boot on the Fedora 20 and Perform a cleanup of all unneeded stuff to reduce the time spent, you don’t want to put old crap
- IMPORTANT: Have a USB stick of at least 1 GB to put a Fedora 20 on it, in case you cannot boot …
- Check you have enough space on the SSD, ideally it should be less than 50% of usage.
Partitioning the HD(s)/SSD(s)
Using either fdisk on command line or gparted for a simple version, partition the disk according to the layout you want to have.
Formatting partitions
If you have a lot of small files, or the reverse a lot of huge file. It is better to perform the format on the command line to setup the size of inodes and other stuff according to the filesystem you have or you want.
Otherwise, if you don’t know just use gparted and stick to an ext4 filesystem.
Setting labels on partitions
Put at least the / mount point…
Copying content on the SSD/HD
- Mount the SSD/HD partitions
- If you use a ext2/ext3/ext4 filesystem, you can go for the simple tar method (I like it very much):
- tar cf – /boot | ( cd /mnt/ | tar xfp – )
- tar cf – /etc | (cd /mnt/ | tar xfp – )
- tar cf – /var | (cd /mnt/ | tar xfp – )
- tar cf – /root | (cd /mnt/ | tar xfp – )
- tar cf – /opt | (cd /mnt/ | tar xfp – )
- tar cf – /home | (cd /mnt | tar xfp – )
- tar cf – /tmp| (cd /mnt | tar xfp – )….
- Create empty dirs for
- dev
- mnt
- run
- sys
- proc
- Add symbolic links on / if any: it is the case on the 64 bits version
Update /etc/fstab in the target HD
Probably the new SSD(s)/HD(s) are having a new ID, you have to find it.
Personally,, I was too lazy so I used the old school way: /dev/sd[a-z][1-9]+.
Then modify the fstab on the new SSD/HD accordingly.
Setup boot loader (grub2)
- As root run the following commands
- grub2-install –recheck /dev/MYHARDDRIVE
- grub2-mkconfig -o /boot/grub2/grub.cfg
- sync
- reboot
- If the system does not boot use the USB key
- Mount partitions for instance in /mnt/sysimage/
- mount –bind /dev /mnt/sysimage/dev
- mount –bind /proc /mnt/sysimage/proc
- mount –bind /sys /mnt/sysimage/sys
- chroot /mnt/sysimage
- Then redo steps from 1. to 4. it should be ok
SSD Specific Tuning
- Check the SSD supports TRIM: sudo hdparm -I /dev/MYSSD | grep TRIM
- Ext4 changes in /etc/fstab add discard in options:
- Example: /dev/sdb1 / ext4 defaults,discard 1 1
- Avoid to swap too early, add this in /etc/sysctl.conf
- #SSD
vm.swappiness = 0
- #SSD
- IO Scheduler change (create /etc/rc.d/rc.local and append this if existing, after enable the rc.local. Google this: “Fedora 20 rc.local” )
#!/usr/bin/bash#SSD Specific
echo ‘noop’ > /sys/block/sdb/queue/scheduler
echo ‘noop’ > /sys/block/sda/queue/schedulerexit 0
I wanna be your dog !
Je suis tombé par hasard sur les accords de “I wanna be u dog”, trop bon !
Merci la peluche
http://tabs.ultimate-guitar.com/i/iggy_pop/i_wanna_be_your_dog_tab.htm
Metallica & Alice in Chains
J’ai un peu continué à bosser:
- One de Metallica (partie lente hein )
- Rooster d’Alice in Chains (Le solo se transpose facilement, j’ai trouvé une petite montée sympa en plus mais encore du boulot pour avoir une descente qui sonne bien)
- Echainement d’accords un peu sympa: E Major, E minor, A, D, A (il manque la rythmique et les répétitions, mais çà sonne pas mal)
- One Metallica (24 sur le stomplab)
Metallica & Alice in Chains
J’ai un peu glandé ces derniers temps… (bronchite) juste un peu de boulot sur les doigts
J’ai continué sur Master of Puppets avec cette série de vidéos :
http://www.youtube.com/watch?v=zGwwUL-PKXI
Jeté un oeil sur l’intro de Metallica One :
http://tabs.ultimate-guitar.com/m/metallica/one_ver2_tab.htm
Alice in Chains, micro solo: (corde 3)
7,6,7,9 9,7,9,6,7(down), 11,12,11
En fait, çà se transpose un peu ou on veut sur le manche
Voir là aussi:
http://tabs.ultimate-guitar.com/a/alice_in_chains/rooster_tab.htm
On peut faire une montée sur une corde au dessus, exemple sur 7,9 par contre j’ai pas encore trouvé une descente “jolie” histoire d’un peu améliorer cette bestiole
Metallica
- Début sur Metallica, Master of Puppets : http://tabs.ultimate-guitar.com/m/metallica/master_of_puppets_tab.htm
- Un peu de rythmique
Blues
- Un peu de Blues histoire de changer
- Bossé sur quelques accords