added subdivcube infill

Esse commit está contido em:
mboerwinkle
2016-10-10 17:13:29 +00:00
commit c339dbc8ae
11 arquivos alterados com 399 adições e 19 exclusões
+1
Ver Arquivo
@@ -84,6 +84,7 @@ set(engine_SRCS # Except main.cpp.
src/infill/ZigzagConnectorProcessorDisconnectedEndPieces.cpp
src/infill/ZigzagConnectorProcessorEndPieces.cpp
src/infill/ZigzagConnectorProcessorNoEndPieces.cpp
src/infill/subDivCube.cpp
src/pathPlanning/Comb.cpp
src/pathPlanning/LinePolygonsCrossings.cpp
+80 -18
Ver Arquivo
@@ -1,20 +1,82 @@
set(CPACK_PACKAGE_VENDOR "Ultimaker")
set(CPACK_PACKAGE_CONTACT "Arjen Hiemstra <a.hiemstra@ultimaker.com>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Cura Engine")
set(CPACK_PACKAGE_VERSION "15.05.90")
set(CPACK_GENERATOR "DEB")
if(NOT DEFINED CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)
# This file will be configured to contain variables for CPack. These variables
# should be set in the CMake list file of the project before CPack module is
# included. The list of available CPACK_xxx variables and their associated
# documentation may be obtained using
# cpack --help-variable-list
#
# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME)
# and some are specific to a generator
# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables
# usually begin with CPACK_<GENNAME>_xxxx.
SET(CPACK_BINARY_7Z "")
SET(CPACK_BINARY_BUNDLE "")
SET(CPACK_BINARY_CYGWIN "")
SET(CPACK_BINARY_DEB "")
SET(CPACK_BINARY_DRAGNDROP "")
SET(CPACK_BINARY_IFW "")
SET(CPACK_BINARY_NSIS "")
SET(CPACK_BINARY_OSXX11 "")
SET(CPACK_BINARY_PACKAGEMAKER "")
SET(CPACK_BINARY_RPM "")
SET(CPACK_BINARY_STGZ "")
SET(CPACK_BINARY_TBZ2 "")
SET(CPACK_BINARY_TGZ "")
SET(CPACK_BINARY_TXZ "")
SET(CPACK_BINARY_TZ "")
SET(CPACK_BINARY_WIX "")
SET(CPACK_BINARY_ZIP "")
SET(CPACK_CMAKE_GENERATOR "Unix Makefiles")
SET(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE")
SET(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE")
SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "arcus (>= 15.05.90), protobuf (>= 3.0.0), libstdc++6 (>= 4.9.0), libgcc1 (>= 4.9.0)")
SET(CPACK_GENERATOR "DEB")
SET(CPACK_INSTALL_CMAKE_PROJECTS "/root/Data/Firm2017/release/CuraEngine;CuraEngine;ALL;/")
SET(CPACK_INSTALL_PREFIX "/usr/local")
SET(CPACK_MODULE_PATH "")
SET(CPACK_NSIS_DISPLAY_NAME "CuraEngine 15.05.90")
SET(CPACK_NSIS_INSTALLER_ICON_CODE "")
SET(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "")
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
SET(CPACK_NSIS_PACKAGE_NAME "CuraEngine 15.05.90")
SET(CPACK_OUTPUT_CONFIG_FILE "/root/Data/Firm2017/release/CuraEngine/CPackConfig.cmake")
SET(CPACK_PACKAGE_CONTACT "Arjen Hiemstra <a.hiemstra@ultimaker.com>")
SET(CPACK_PACKAGE_DEFAULT_LOCATION "/")
SET(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-3.6/Templates/CPack.GenericDescription.txt")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Cura Engine")
SET(CPACK_PACKAGE_FILE_NAME "CuraEngine-15.05.90_")
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "CuraEngine 15.05.90")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "CuraEngine 15.05.90")
SET(CPACK_PACKAGE_NAME "CuraEngine")
SET(CPACK_PACKAGE_RELOCATABLE "true")
SET(CPACK_PACKAGE_VENDOR "Ultimaker")
SET(CPACK_PACKAGE_VERSION "15.05.90")
SET(CPACK_PACKAGE_VERSION_MAJOR "0")
SET(CPACK_PACKAGE_VERSION_MINOR "1")
SET(CPACK_PACKAGE_VERSION_PATCH "1")
SET(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake-3.6/Templates/CPack.GenericLicense.txt")
SET(CPACK_RESOURCE_FILE_README "/usr/share/cmake-3.6/Templates/CPack.GenericDescription.txt")
SET(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-3.6/Templates/CPack.GenericWelcome.txt")
SET(CPACK_SET_DESTDIR "OFF")
SET(CPACK_SOURCE_7Z "")
SET(CPACK_SOURCE_CYGWIN "")
SET(CPACK_SOURCE_GENERATOR "TBZ2;TGZ;TXZ;TZ")
SET(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/root/Data/Firm2017/release/CuraEngine/CPackSourceConfig.cmake")
SET(CPACK_SOURCE_TBZ2 "ON")
SET(CPACK_SOURCE_TGZ "ON")
SET(CPACK_SOURCE_TXZ "ON")
SET(CPACK_SOURCE_TZ "ON")
SET(CPACK_SOURCE_ZIP "OFF")
SET(CPACK_SYSTEM_NAME "Linux")
SET(CPACK_TOPLEVEL_TAG "Linux")
SET(CPACK_WIX_SIZEOF_VOID_P "8")
if(NOT CPACK_PROPERTIES_FILE)
set(CPACK_PROPERTIES_FILE "/root/Data/Firm2017/release/CuraEngine/CPackProperties.cmake")
endif()
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
set(DEB_DEPENDS
"arcus (>= 15.05.90)"
"protobuf (>= 3.0.0)"
"libstdc++6 (>= 4.9.0)"
"libgcc1 (>= 4.9.0)"
)
string(REPLACE ";" ", " DEB_DEPENDS "${DEB_DEPENDS}")
set(CPACK_DEBIAN_PACKAGE_DEPENDS ${DEB_DEPENDS})
include(CPack)
if(EXISTS ${CPACK_PROPERTIES_FILE})
include(${CPACK_PROPERTIES_FILE})
endif()
+1 -1
Ver Arquivo
@@ -44,7 +44,7 @@
//#define use_xyz
//use_lines: Enables line clipping. Adds a very minor cost to performance.
//#define use_lines
#define use_lines
//use_deprecated: Enables temporary support for the obsolete functions
//#define use_deprecated
+5
Ver Arquivo
@@ -421,6 +421,11 @@ void FffPolygonGenerator::processDerivedWallsSkinInfill(SliceMeshStorage& mesh,
// create gradual infill areas
SkinInfillAreaComputation::generateGradualInfill(mesh, mesh.getSettingInMicrons("gradual_infill_step_height"), mesh.getSettingAsCount("gradual_infill_steps"));
//SubDivCube Pre-compute Octree
if(mesh.getSettingAsFillMethod("infill_pattern") == EFillMethod::CUBICSUBDIV){
SubDivCube::init(mesh);
}
// combine infill
unsigned int combined_infill_layers = std::max(1U, round_divide(mesh.getSettingInMicrons("infill_sparse_thickness"), std::max(getSettingInMicrons("layer_height"), 1))); //How many infill layers to combine to obtain the requested sparse thickness.
combineInfillLayers(mesh,combined_infill_layers);
+26
Ver Arquivo
@@ -48,6 +48,9 @@ void Infill::generate(Polygons& result_polygons, Polygons& result_lines)
case EFillMethod::ZIG_ZAG:
generateZigZagInfill(result_lines, line_distance, fill_angle, connected_zigzags, use_endpieces);
break;
case EFillMethod::CUBICSUBDIV:
generateCubicSubDivInfill(result_lines);
break;
default:
logError("Fill pattern has unknown value.\n");
break;
@@ -97,6 +100,29 @@ void Infill::generateTriangleInfill(Polygons& result)
generateLineInfill(result, line_distance, fill_angle + 120, 0);
}
void Infill::generateCubicSubDivInfill(Polygons& result)
{
Polygons uncropped;
baseSubDivCube->draw(z, uncropped, NULL);
addLineSegmentsInfill(result, uncropped);
}
void Infill::addLineSegmentsInfill(Polygons& result, Polygons& input)
{
auto addLine = [&](Point from, Point to)
{
PolygonRef p = result.newPoly();
p.add(from);
p.add(to);
};
ClipperLib::PolyTree goodSegsTree = in_outline.lineSegIntersection(input);
ClipperLib::Paths goodSegs;
ClipperLib::OpenPathsFromPolyTree(goodSegsTree, goodSegs);
for(uint64_t idx = 0; idx < goodSegs.size(); idx++){
addLine(goodSegs[idx][0], goodSegs[idx][1]);
}
}
void Infill::addLineInfill(Polygons& result, const PointMatrix& rotation_matrix, const int scanline_min_idx, const int line_distance, const AABB boundary, std::vector<std::vector<int64_t>>& cut_list, int64_t shift)
{
auto addLine = [&](Point from, Point to)
+14
Ver Arquivo
@@ -12,6 +12,7 @@
#include "infill/ZigzagConnectorProcessorEndPieces.h"
#include "infill/ZigzagConnectorProcessorConnectedEndPieces.h"
#include "infill/ZigzagConnectorProcessorDisconnectedEndPieces.h"
#include "infill/subDivCube.h"
#include "utils/intpoint.h"
#include "utils/AABB.h"
@@ -99,6 +100,12 @@ private:
* \param result (output) The resulting lines
*/
void generateTriangleInfill(Polygons& result);
/*!
* Generate a 3d pattern of subdivided cubes on their points
* \param result (output) The resulting lines
*/
void generateCubicSubDivInfill(Polygons& result);
/*!
* Convert a mapping from scanline to line_segment-scanline-intersections (\p cut_list) into line segments, using the even-odd rule
@@ -112,6 +119,13 @@ private:
*/
void addLineInfill(Polygons& result, const PointMatrix& rotation_matrix, const int scanline_min_idx, const int line_distance, const AABB boundary, std::vector<std::vector<int64_t>>& cut_list, int64_t total_shift);
/*!
* Crop line segments by the infill polygon using Clipper
* \param result (output) The resulting lines
* \param input The line segments to be cropped
*/
void addLineSegmentsInfill(Polygons& result, Polygons& input);
/*!
* generate lines within the area of \p in_outline, at regular intervals of \p line_distance
*
+226
Ver Arquivo
@@ -0,0 +1,226 @@
#include "subDivCube.h"
#include "functional"
#include "../utils/polygonUtils.h"
#include "../sliceDataStorage.h"
namespace cura {
SubDivCube* baseSubDivCube;
double SubDivCube::rotCoefX;
double SubDivCube::rotCoefY;
std::vector<int64_t> SubDivCube::sideLen;
std::vector<int64_t> SubDivCube::height;
std::vector<int64_t> SubDivCube::maxDrawDiff;
std::vector<int64_t> SubDivCube::squareCutAcross;
std::vector<int64_t> SubDivCube::maxLineOffset;
double SubDivCube::radMult = 1;
int32_t SubDivCube::radAdd = 0;
void SubDivCube::draw(int64_t z, Polygons& result, Polygons** dir)
{
int epsilon = 10;
auto addLine = [&](Point from, Point to)//this simply adds a line segment to result
{
PolygonRef p = result.newPoly();
p.add(from);
p.add(to);
};
auto addLineAndCombine = [&](Polygons& group, Point from, Point to)//this adds a line segment to a polygon of parallel line segments and combines segments that touch within epsilon
{
for(int x = 0; x < group.size(); x++){
if(abs(from.X-group[x][1].X)<epsilon && abs(from.Y-group[x][1].Y)<epsilon){
from = group[x][0];
group.remove(x);
x--;
continue;
}
if(abs(to.X-group[x][0].X)<epsilon && abs(to.Y-group[x][0].Y)<epsilon){
to = group[x][1];
group.remove(x);
x--;
continue;
}
}
PolygonRef p = group.newPoly();
p.add(from);
p.add(to);
};
int topLevel = 0;//if this cube is the top level (ie root of octree).
if(dir == NULL){//if the three directional polygons have not yet been created, then this is the root of the recursive draw call
dir = (Polygons**)calloc(3, sizeof(Polygons*));
for(int temp = 0; temp < 3; temp++) dir[temp] = new Polygons();
topLevel=1;
}
int32_t diff = abs(z-center.z);//z difference from current layer
if(diff>height[d]/2){//outside of cube. No drawing or subdivision needed
return;
}
if(diff<maxDrawDiff[d]){//inside of drawing range
Point rela, relb, a, b;
rela.X=(squareCutAcross[d]/2)*((double)(maxDrawDiff[d]-diff)/(double)maxDrawDiff[d]);//rela and relb are relative coordinates of the two end points of the drawn line from the cube center
relb.X=-rela.X;
rela.Y=maxLineOffset[d]-((z-(center.z-maxDrawDiff[d]))*(1/sqrt(2)));
relb.Y=rela.Y;
initRot(rela);
initRot(relb);
for(int temp = 0; temp < 3; temp++){//draw and rotate
a.X = center.x+rela.X;
a.Y = center.y+rela.Y;
b.X = center.x+relb.X;
b.Y = center.y+relb.Y;
addLineAndCombine(*(dir[temp]), a, b);
if(temp < 2){
rot120(rela);
rot120(relb);
}
}
}
for(int temp = 0; temp < 8; temp++){//draw all children too
if(children[temp] != NULL){
children[temp]->draw(z, result, dir);
}
}
if(topLevel){//take care of copying the contents of the three directional polygons into result set AND free the three directional polygons
for(int temp = 0; temp < 3; temp++){
for(unsigned int x = 0; x < dir[temp]->size(); x++){
addLine((*dir[temp])[x][0], (*dir[temp])[x][1]);
}
delete dir[temp];
}
free(dir);
}
}
SubDivCube::SubDivCube(SliceMeshStorage& mesh, Point3& myCenter, int d){
this->d = d;//d is depth of current recursion. kind of. except 0 is completely recursed...
center = myCenter;
if(d == 0) return;//Lowest layer, no need for subdivision.
Point3 c;//c will be the centers of the new 8 cubes
int32_t nsideLen = sideLen[d-1];//the new sideLen is the sideLen for recursed one more time...
long int rad = radMult*height[d]/4+radAdd;//note:divided by four because it is half of half of the parent height.
//top
c.x=center.x;
c.y=center.y;
c.z=center.z+(height[d]/4);
if(subDiv(mesh, c, nsideLen, rad)){
children[0] = new SubDivCube(mesh, c, d-1);
}
//top three
Point relCenter;
c.z=center.z+height[d]/12;
relCenter.X=0;
relCenter.Y=-maxLineOffset[d];
initRot(relCenter);
for(int temp = 0; temp < 3; temp++){
c.x = relCenter.X+center.x;
c.y = relCenter.Y+center.y;
if(subDiv(mesh, c, nsideLen, rad)){
children[temp+1] = new SubDivCube(mesh, c, d-1);
}
if(temp < 2){
rot120(relCenter);
}
}
//bottom
c.x=center.x;
c.y=center.y;
c.z=center.z-(height[d]/4);
if(subDiv(mesh, c, nsideLen, rad)){
children[4] = new SubDivCube(mesh, c, d-1);
}
//botton three
c.z=center.z-height[d]/12;
relCenter.X=0;
relCenter.Y=maxLineOffset[d];
initRot(relCenter);
for(int temp = 0; temp < 3; temp++){
c.x = relCenter.X+center.x;
c.y = relCenter.Y+center.y;
if(subDiv(mesh, c, nsideLen, rad)){
children[temp+5] = new SubDivCube(mesh, c, d-1);
}
if(temp < 2){
rot120(relCenter);
}
}
}
int SubDivCube::subDiv(SliceMeshStorage& mesh, Point3& center, int32_t sideLen, int32_t rad){//put inside of constructor as a lambda? (returns one if a described cube should be subdivided, else zero)
int32_t distance;
long int heightRad;//radius of sphere slice on target layer
int insideSomewhere = 0;
int outsideSomewhere = 0;
int inside;
double partDist;
long int layer_height = mesh.getSettingInMicrons("layer_height");
long int bot_layer = (center.z-(rad))/layer_height;
long int top_layer = (center.z+(rad))/layer_height;
for(long int templayer = bot_layer; templayer <= top_layer; templayer+=3/*plus three as a quick speed fix... 3 layers doesn't seem like to many?*/){
partDist = (double)(templayer*layer_height-center.z)/rad;//how far through the radius are we (0-1)
heightRad = rad*(sqrt(1-(partDist*partDist)));//radius of circumscribed sphere at this level
Point loc(center.x, center.y);
inside = dist(mesh, templayer, loc, &distance);
if(inside == 1){//0 = outside, 1 = inside, 2 = invalid layer(outside)//FIXME LAST does the 2 option cause a speed-up?
insideSomewhere = 1;
}else{
outsideSomewhere = 1;
}
if(outsideSomewhere && insideSomewhere){
return 1;
}
if((inside!=2)&&abs(distance) < heightRad){
return 1;
}
}
return 0;
}
int SubDivCube::dist(SliceMeshStorage& mesh, long int layer_nr, Point& loc, int32_t* dist){
if(layer_nr < 0 || layer_nr>=mesh.layers.size()){//if this layer is outside of existing layer range...
return 2;
}
Polygons collide;
mesh.layers[layer_nr].getSecondOrInnermostWalls(collide);
Point centerpoint = loc;
bool inside = collide.inside(centerpoint);
ClosestPolygonPoint rimpoint = PolygonUtils::moveInside2(collide, centerpoint);
*dist = sqrt((rimpoint.location.X-loc.X)*(rimpoint.location.X-loc.X)+(rimpoint.location.Y-loc.Y)*(rimpoint.location.Y-loc.Y));
if(inside){
return 1;
}
return 0;
}
void SubDivCube::init(SliceMeshStorage& gMesh){
radMult = 1;//gMesh.getSettingInMillimeters("sub_div_rad_mult");
radAdd = 0;//gMesh.getSettingInMicrons("sub_div_rad_add");
rotCoefX = cos(M_PI/4);//90 degrees hard coded in because it is for the other infills too. This prevents any of the three directions from being parallel to x or y axis
rotCoefY = sin(M_PI/4);
int maxDepth = 0;
for(int64_t maxSideLen = gMesh.getSettingInMicrons("infill_line_distance")*2; maxSideLen < 25600000; maxSideLen *= 2){//beginning at zero (most recursed) precompute values
sideLen.push_back(maxSideLen);
height.push_back(sqrt(maxSideLen*maxSideLen*3));
squareCutAcross.push_back(sqrt(maxSideLen*maxSideLen*2));
maxDrawDiff.push_back((1.0/sqrt(3.0))*maxSideLen);
maxLineOffset.push_back((sqrt(2.0/3.0)*maxSideLen)/2);
maxDepth++;
}
Point3 center(0, 0, 0);
baseSubDivCube = new SubDivCube(gMesh, center, maxDepth-1);
}
void SubDivCube::initRot(Point& targ){//perform initial rotation.
int64_t x;
x = rotCoefX*targ.X-rotCoefY*targ.Y;
targ.Y = rotCoefX*targ.Y+rotCoefY*targ.X;
targ.X = x;
}
void SubDivCube::rot120(Point& targ){//rotate 120 degrees
int64_t x;
x = (-0.5)*targ.X-(sqrt_three_fourths)*targ.Y;
targ.Y = (-0.5)*targ.Y+(sqrt_three_fourths)*targ.X;
targ.X = x;
}
}//namespace cura
+34
Ver Arquivo
@@ -0,0 +1,34 @@
#ifndef SUBDIVCUBE_H
#define SUBDIVCUBE_H
#include "../sliceDataStorage.h"
namespace cura
{
class Infill;
class SubDivCube
{
public:
static void init(SliceMeshStorage& gMesh);
void draw(int64_t z, Polygons& result, Polygons** dir);
private:
static constexpr double sqrt_three_fourths = 0.8660254037844386467637231707529361834714026269051903;//this is used for the 120 degree rotation...
SubDivCube(SliceMeshStorage& mesh, Point3& myCenter, int d);
static std::vector<int64_t> sideLen;//length of cube side
static std::vector<int64_t> height;//height of cube
static std::vector<int64_t> squareCutAcross;//length across face of cube
static std::vector<int64_t> maxDrawDiff;//maximum difference from the center level of the cube in the x axis when lines still need to be drawn.
static std::vector<int64_t> maxLineOffset;//maximum distance from the 2d center that subdividing lines should be drawn at
static double radMult;
static int32_t radAdd;
int d;
Point3 center;//location of cube center
SubDivCube *(children[8]) = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
static int dist(SliceMeshStorage& mesh, long int layer_nr, Point& loc, int32_t* dist);//returns 1 if inside, distance from polygon put into dist
static int subDiv(SliceMeshStorage& mesh, Point3& center, int32_t sideLen, int32_t rad);
static void rot120(Point& targ);
static void initRot(Point& targ);
static double rotCoefX;
static double rotCoefY;
};
extern SubDivCube *baseSubDivCube;//the big cube that encompasses everything
}
#endif
+2
Ver Arquivo
@@ -345,6 +345,8 @@ EFillMethod SettingsBaseVirtual::getSettingAsFillMethod(std::string key) const
return EFillMethod::GRID;
if (value == "cubic")
return EFillMethod::CUBIC;
if (value == "cubicsubdiv")
return EFillMethod::CUBICSUBDIV;
if (value == "tetrahedral")
return EFillMethod::TETRAHEDRAL;
if (value == "triangles")
+1
Ver Arquivo
@@ -105,6 +105,7 @@ enum class EFillMethod
LINES,
GRID,
CUBIC,
CUBICSUBDIV,
TETRAHEDRAL,
TRIANGLES,
CONCENTRIC,
+9
Ver Arquivo
@@ -514,6 +514,15 @@ public:
clipper.Execute(ClipperLib::ctIntersection, ret.paths);
return ret;
}
ClipperLib::PolyTree lineSegIntersection(const Polygons& other) const
{
ClipperLib::PolyTree ret;
ClipperLib::Clipper clipper(clipper_init);
clipper.AddPaths(paths, ClipperLib::ptClip, true);
clipper.AddPaths(other.paths, ClipperLib::ptSubject, false);
clipper.Execute(ClipperLib::ctIntersection, ret);
return ret;
}
Polygons xorPolygons(const Polygons& other) const
{
Polygons ret;