Comparar commits

..

13 Commits

Autor SHA1 Mensagem Data
Tim Kuipers 693921d644 Merge branch 'feature_anti_support' into feature_support_mesh 2016-11-02 16:01:41 +01:00
Tim Kuipers dbe6269262 Revert "refactor: support_mesh ==> overhang_mesh (CURA-2077)"
This reverts commit 00041da2df.
2016-11-02 16:01:08 +01:00
Tim Kuipers ac2bbd9c39 Merge branch 'feature_anti_support' into feature_support_mesh 2016-11-02 15:56:25 +01:00
Tim Kuipers 9d56baba41 fix: keep SliceMeshStorage aligned with Mesh (CURA-2077) 2016-10-20 09:38:25 +02:00
Tim Kuipers 24c9384253 preliminaries to support_mesh (CURA-2747) 2016-10-19 17:35:13 +02:00
Tim Kuipers 00041da2df refactor: support_mesh ==> overhang_mesh (CURA-2077) 2016-10-19 16:42:50 +02:00
Tim Kuipers 3c7c352bfc fix: add support during generation, causing all support settings to be applied to support meshes (CURA-2077)
This has the disadvantage that support meshes are re-evaluated for each normal mesh.
However, otherwise support meshes could overlap with each other mesh..
2016-10-14 16:44:50 +02:00
Tim Kuipers 66e6375942 fix: lil typo in AreaSupport::generateSupportAreas for support meshes (CURA-2077) 2016-10-14 16:43:26 +02:00
Tim Kuipers 8d3f66c2cb fix: don't switch extruder if support interface is too small to be printed (CURA-2077) 2016-10-14 16:41:15 +02:00
Tim Kuipers 1fd540c231 fix: also print support of support meshes above normal support (CURA-2077) 2016-10-14 16:00:45 +02:00
Tim Kuipers ac799dd00e fix: don't do multi volumes functions on support meshes (CURA-2077) 2016-10-14 16:00:22 +02:00
Tim Kuipers 699406b044 refactor: anti_support_mesh ==> anti_overhang_mesh (CURA-2077) 2016-10-14 15:31:53 +02:00
Tim Kuipers 2f3333e87c feat: anti support meshes (CURA-2077) 2016-10-14 15:30:19 +02:00
30 arquivos alterados com 223 adições e 401 exclusões
-14
Ver Arquivo
@@ -42,20 +42,6 @@ if(NOT APPLE AND NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
endif()
if(WIN32)
add_definitions(/DNOMINMAX)
if (MSVC)
# Switch the runtime to use static linking on MSVC
foreach(flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)
endif()
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} libs)
add_library(clipper STATIC libs/clipper/clipper.cpp)
-1
Ver Arquivo
@@ -31,7 +31,6 @@ CMake compilation:
4. ```$ make```
Project files generation:
1. Navigate to the CuraEngine directory and execute the following commands
2. ```cmake . -G "CodeBlocks - Unix Makefiles"```
3. (for a list of supported IDE's see http://www.cmake.org/Wiki/CMake_Generator_Specific_Information#Code::Blocks_Generator)
+1 -1
Ver Arquivo
@@ -7,4 +7,4 @@ This is the documentation for CuraEngine, the back-end slicer of Cura.
[Glossary](documentation/glossary.md)
[Code Conventions](https://github.com/Ultimaker/Meta/blob/master/code_conventions.md)
[Code Conventions](documentation/code_conventions.md)
+5 -1
Ver Arquivo
@@ -1077,7 +1077,6 @@ void FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlan
int skin_extruder_nr = getSettingAsIndex("support_interface_extruder_nr");
const ExtruderTrain& interface_extr = *storage.meshgroup->getExtruderTrain(skin_extruder_nr);
setExtruder_addPrime(storage, gcode_layer, layer_nr, skin_extruder_nr);
EFillMethod pattern = interface_extr.getSettingAsFillMethod("support_interface_pattern");
int support_line_distance = interface_extr.getSettingInMicrons("support_interface_line_distance");
@@ -1115,6 +1114,11 @@ void FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlan
Polygons support_lines;
infill_comp.generate(support_polygons, support_lines);
if (support_polygons.size() == 0 && support_lines.size() == 0)
{
return;
}
setExtruder_addPrime(storage, gcode_layer, layer_nr, skin_extruder_nr);
gcode_layer.addPolygonsByOptimizer(support_polygons, &storage.support_skin_config);
gcode_layer.addLinesByOptimizer(support_lines, &storage.support_skin_config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
}
+47 -56
Ver Arquivo
@@ -4,7 +4,6 @@
#include <map> // multimap (ordered map allowing duplicate keys)
#include "utils/math.h"
#include "utils/algorithm.h"
#include "slicer.h"
#include "utils/gettime.h"
#include "utils/logoutput.h"
@@ -108,7 +107,7 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
for(unsigned int meshIdx=0; meshIdx < slicerList.size(); meshIdx++)
{
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
if (mesh.getSettingBoolean("conical_overhang_enabled"))
if (mesh.getSettingBoolean("conical_overhang_enabled") && !mesh.getSettingBoolean("anti_overhang_mesh"))
{
ConicalOverhang::apply(slicerList[meshIdx], mesh.getSettingInAngleRadians("conical_overhang_angle"), layer_thickness);
}
@@ -116,19 +115,54 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
Progress::messageProgressStage(Progress::Stage::PARTS, &timeKeeper);
if (storage.getSettingBoolean("carve_multiple_volumes"))
{
carveMultipleVolumes(slicerList);
}
carveMultipleVolumes(slicerList);
AreaSupport::handleSupportMeshes(storage, slicerList);
generateMultipleVolumesOverlap(slicerList);
size_t max_layer_count = 0;
for (unsigned int meshIdx = 0; meshIdx < slicerList.size(); meshIdx++)
{
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
Slicer* slicer = slicerList[meshIdx];
if (!mesh.getSettingBoolean("anti_overhang_mesh") && !mesh.getSettingBoolean("infill_mesh"))
{
max_layer_count = std::max(max_layer_count, slicer->layers.size());
}
}
storage.support.supportLayers.resize(max_layer_count);
storage.meshes.reserve(slicerList.size()); // causes there to be no resize in meshes so that the pointers in sliceMeshStorage._config to retraction_config don't get invalidated.
for (unsigned int meshIdx = 0; meshIdx < slicerList.size(); meshIdx++)
{
Slicer* slicer = slicerList[meshIdx];
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
// always make a new SliceMeshStorage, so that they have the same ordering / indexing as meshgroup.meshes
storage.meshes.emplace_back(&meshgroup->meshes[meshIdx], slicer->layers.size()); // new mesh in storage had settings from the Mesh
SliceMeshStorage& meshStorage = storage.meshes.back();
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
if (mesh.getSettingBoolean("anti_overhang_mesh"))
{
for (unsigned int layer_nr = 0; layer_nr < slicer->layers.size(); layer_nr++)
{
SupportLayer& support_layer = storage.support.supportLayers[layer_nr];
SlicerLayer& slicer_layer = slicer->layers[layer_nr];
support_layer.anti_overhang = support_layer.anti_overhang.unionPolygons(slicer_layer.polygons);
}
continue;
}
if (mesh.getSettingBoolean("support_mesh"))
{
for (unsigned int layer_nr = 0; layer_nr < slicer->layers.size(); layer_nr++)
{
SupportLayer& support_layer = storage.support.supportLayers[layer_nr];
SlicerLayer& slicer_layer = slicer->layers[layer_nr];
support_layer.support_mesh.add(slicer_layer.polygons);
}
continue;
}
createLayerParts(meshStorage, slicer, mesh.getSettingBoolean("meshfix_union_all"), mesh.getSettingBoolean("meshfix_union_all_remove_holes"));
delete slicerList[meshIdx];
@@ -172,7 +206,7 @@ void FffPolygonGenerator::slices2polygons(SliceDataStorage& storage, TimeKeeper&
unsigned int slice_layer_count = 0;
for (SliceMeshStorage& mesh : storage.meshes)
{
if (!mesh.getSettingBoolean("infill_mesh"))
if (!mesh.getSettingBoolean("infill_mesh") && !mesh.getSettingBoolean("anti_overhang_mesh"))
{
slice_layer_count = std::max<unsigned int>(slice_layer_count, mesh.layers.size());
}
@@ -260,9 +294,8 @@ void FffPolygonGenerator::slices2polygons(SliceDataStorage& storage, TimeKeeper&
}
*/
computePrintHeightStatistics(storage);
// handle helpers
storage.primeTower.computePrimeTowerMax(storage);
storage.primeTower.generatePaths(storage, print_layer_count);
logDebug("Processing ooze shield\n");
@@ -497,7 +530,6 @@ void FffPolygonGenerator::removeEmptyFirstLayers(SliceDataStorage& storage, cons
{
layer.printZ -= n_empty_first_layers * layer_height;
}
mesh.layer_nr_max_filled_layer -= n_empty_first_layers;
}
total_layers -= n_empty_first_layers;
}
@@ -527,47 +559,6 @@ void FffPolygonGenerator::processSkinsAndInfill(SliceMeshStorage& mesh, unsigned
}
}
void FffPolygonGenerator::computePrintHeightStatistics(SliceDataStorage& storage)
{
int extruder_count = storage.meshgroup->getExtruderCount();
std::vector<int>& max_print_height_per_extruder = storage.max_print_height_per_extruder;
assert(max_print_height_per_extruder.size() == 0 && "storage.max_print_height_per_extruder shouldn't have been initialized yet!");
max_print_height_per_extruder.resize(extruder_count, -1); // unitialize all as -1
{ // compute max_object_height_per_extruder
for (SliceMeshStorage& mesh : storage.meshes)
{
unsigned int extr_nr = mesh.getSettingAsIndex("extruder_nr");
max_print_height_per_extruder[extr_nr] =
std::max( max_print_height_per_extruder[extr_nr]
, mesh.layer_nr_max_filled_layer );
}
int support_infill_extruder_nr = storage.getSettingAsIndex("support_infill_extruder_nr"); // TODO: support extruder should be configurable per object
max_print_height_per_extruder[support_infill_extruder_nr] =
std::max( max_print_height_per_extruder[support_infill_extruder_nr]
, storage.support.layer_nr_max_filled_layer );
int support_skin_extruder_nr = storage.getSettingAsIndex("support_interface_extruder_nr"); // TODO: support skin extruder should be configurable per object
max_print_height_per_extruder[support_skin_extruder_nr] =
std::max( max_print_height_per_extruder[support_skin_extruder_nr]
, storage.support.layer_nr_max_filled_layer );
int adhesion_extruder_nr = storage.getSettingAsIndex("adhesion_extruder_nr");
max_print_height_per_extruder[adhesion_extruder_nr] =
std::max(0, max_print_height_per_extruder[support_skin_extruder_nr]);
}
storage.max_print_height_order = order(max_print_height_per_extruder);
if (extruder_count >= 2)
{
int second_highest_extruder = storage.max_print_height_order[extruder_count - 2];
storage.max_print_height_second_to_last_extruder = max_print_height_per_extruder[second_highest_extruder];
}
else
{
storage.max_print_height_second_to_last_extruder = -1;
}
}
void FffPolygonGenerator::processOozeShield(SliceDataStorage& storage)
{
if (!getSettingBoolean("ooze_shield_enabled"))
@@ -577,7 +568,7 @@ void FffPolygonGenerator::processOozeShield(SliceDataStorage& storage)
const int ooze_shield_dist = getSettingInMicrons("ooze_shield_dist");
for (int layer_nr = 0; layer_nr <= storage.max_print_height_second_to_last_extruder; layer_nr++)
for (int layer_nr = 0; layer_nr <= storage.max_object_height_second_to_last_extruder; layer_nr++)
{
storage.oozeShield.push_back(storage.getLayerOutlines(layer_nr, true).offset(ooze_shield_dist, ClipperLib::jtRound));
}
@@ -586,18 +577,18 @@ void FffPolygonGenerator::processOozeShield(SliceDataStorage& storage)
if (angle <= 89)
{
int allowed_angle_offset = tan(getSettingInAngleRadians("ooze_shield_angle")) * getSettingInMicrons("layer_height"); // Allow for a 60deg angle in the oozeShield.
for (int layer_nr = 1; layer_nr <= storage.max_print_height_second_to_last_extruder; layer_nr++)
for (int layer_nr = 1; layer_nr <= storage.max_object_height_second_to_last_extruder; layer_nr++)
{
storage.oozeShield[layer_nr] = storage.oozeShield[layer_nr].unionPolygons(storage.oozeShield[layer_nr - 1].offset(-allowed_angle_offset));
}
for (int layer_nr = storage.max_print_height_second_to_last_extruder; layer_nr > 0; layer_nr--)
for (int layer_nr = storage.max_object_height_second_to_last_extruder; layer_nr > 0; layer_nr--)
{
storage.oozeShield[layer_nr - 1] = storage.oozeShield[layer_nr - 1].unionPolygons(storage.oozeShield[layer_nr].offset(-allowed_angle_offset));
}
}
const float largest_printed_area = 1.0; // TODO: make var a parameter, and perhaps even a setting?
for (int layer_nr = 0; layer_nr <= storage.max_print_height_second_to_last_extruder; layer_nr++)
for (int layer_nr = 0; layer_nr <= storage.max_object_height_second_to_last_extruder; layer_nr++)
{
storage.oozeShield[layer_nr].removeSmallAreas(largest_printed_area);
}
+1 -8
Ver Arquivo
@@ -118,14 +118,7 @@ private:
* \param total_layers The total number of layers
*/
void removeEmptyFirstLayers(SliceDataStorage& storage, const int layer_height, unsigned int& total_layers);
/*!
* Set \ref SliceDataStorage::max_print_height_per_extruder and \ref SliceDataStorage::max_print_height_order and \ref SliceDataStorage::max_print_height_second_to_last_extruder
*
* \param[in,out] storage Where to retrieve mesh and support etc settings from and where the print height statistics are saved.
*/
void computePrintHeightStatistics(SliceDataStorage& storage);
/*!
* Generate the inset polygons which form the walls.
* \param mesh Input and Output parameter: fetches the outline information (see SliceLayerPart::outline) and generates the other reachable field of the \p storage
+1 -1
Ver Arquivo
@@ -60,7 +60,7 @@ bool FffProcessor::processMeshGroup(MeshGroup* meshgroup)
bool empty = true;
for (Mesh& mesh : meshgroup->meshes)
{
if (!mesh.getSettingBoolean("infill_mesh"))
if (!mesh.getSettingBoolean("infill_mesh") && !mesh.getSettingBoolean("anti_overhang_mesh"))
{
empty = false;
}
-2
Ver Arquivo
@@ -1,8 +1,6 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <string.h>
#ifndef WIN32
#include <strings.h>
#endif
#include <stdio.h>
#include "MeshGroup.h"
+58 -4
Ver Arquivo
@@ -50,6 +50,61 @@ void PrimeTower::setConfigs(const MeshGroup* meshgroup, const int layer_thicknes
}
}
void PrimeTower::computePrimeTowerMax(SliceDataStorage& storage)
{ // compute storage.max_object_height_second_to_last_extruder, which is used to determine the highest point in the prime tower
extruder_count = storage.meshgroup->getExtruderCount();
int max_object_height_per_extruder[extruder_count];
std::fill_n(max_object_height_per_extruder, extruder_count, -1); // unitialize all as -1
{ // compute max_object_height_per_extruder
for (SliceMeshStorage& mesh : storage.meshes)
{
unsigned int extr_nr = mesh.getSettingAsIndex("extruder_nr");
max_object_height_per_extruder[extr_nr] =
std::max( max_object_height_per_extruder[extr_nr]
, mesh.layer_nr_max_filled_layer );
}
int support_infill_extruder_nr = storage.getSettingAsIndex("support_infill_extruder_nr"); // TODO: support extruder should be configurable per object
max_object_height_per_extruder[support_infill_extruder_nr] =
std::max( max_object_height_per_extruder[support_infill_extruder_nr]
, storage.support.layer_nr_max_filled_layer );
int support_skin_extruder_nr = storage.getSettingAsIndex("support_interface_extruder_nr"); // TODO: support skin extruder should be configurable per object
max_object_height_per_extruder[support_skin_extruder_nr] =
std::max( max_object_height_per_extruder[support_skin_extruder_nr]
, storage.support.layer_nr_max_filled_layer );
}
{ // // compute max_object_height_second_to_last_extruder
int extruder_max_object_height = 0;
for (int extruder_nr = 1; extruder_nr < extruder_count; extruder_nr++)
{
if (max_object_height_per_extruder[extruder_nr] > max_object_height_per_extruder[extruder_max_object_height])
{
extruder_max_object_height = extruder_nr;
}
}
int extruder_second_max_object_height = -1;
for (int extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++)
{
if (extruder_nr == extruder_max_object_height) { continue; }
if (extruder_second_max_object_height == -1 || max_object_height_per_extruder[extruder_nr] > max_object_height_per_extruder[extruder_second_max_object_height])
{
extruder_second_max_object_height = extruder_nr;
}
}
if (extruder_second_max_object_height < 0)
{
storage.max_object_height_second_to_last_extruder = -1;
}
else
{
storage.max_object_height_second_to_last_extruder = max_object_height_per_extruder[extruder_second_max_object_height];
}
}
}
void PrimeTower::generateGroundpoly(const SliceDataStorage& storage)
{
PolygonRef p = ground_poly.newPoly();
@@ -67,8 +122,7 @@ void PrimeTower::generateGroundpoly(const SliceDataStorage& storage)
void PrimeTower::generatePaths(const SliceDataStorage& storage, unsigned int total_layers)
{
extruder_count = storage.meshgroup->getExtruderCount();
if (storage.max_print_height_second_to_last_extruder >= 0 && storage.getSettingBoolean("prime_tower_enable"))
if (storage.max_object_height_second_to_last_extruder >= 0 && storage.getSettingBoolean("prime_tower_enable"))
{
generatePaths_denseInfill(storage);
generateWipeLocations(storage);
@@ -106,7 +160,7 @@ void PrimeTower::generatePaths_denseInfill(const SliceDataStorage& storage)
void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, const GCodeExport& gcode, const int layer_nr, const int prev_extruder, bool wipe)
{
if (!( storage.max_print_height_second_to_last_extruder >= 0 && storage.getSettingInMicrons("prime_tower_size") > 0) )
if (!( storage.max_object_height_second_to_last_extruder >= 0 && storage.getSettingInMicrons("prime_tower_size") > 0) )
{
return;
}
@@ -120,7 +174,7 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcode
return;
}
if (layer_nr > storage.max_print_height_second_to_last_extruder + 1)
if (layer_nr > storage.max_object_height_second_to_last_extruder + 1)
{
return;
}
+7
Ver Arquivo
@@ -75,6 +75,13 @@ public:
*/
void generatePaths(const SliceDataStorage& storage, unsigned int total_layers);
/*!
* Compute the maximum layer at which a layer switch will occur and store the result in \ref SliceDataStorage::max_object_height_second_to_last_extruder
*
* \param[in,out] storage Where to retrieve area data and extruder settings for those areas; where to store the max_object_height_second_to_last_extruder
*/
void computePrimeTowerMax(SliceDataStorage& storage);
PrimeTower(); //!< basic constructor
/*!
-2
Ver Arquivo
@@ -2,9 +2,7 @@
#include <cmath> // sqrt
#include <fstream> // debug IO
#ifndef WIN32
#include <unistd.h>
#endif
#include "progress/Progress.h"
#include "weaveDataStorage.h"
+1 -1
Ver Arquivo
@@ -14,7 +14,7 @@
#include <string> // stoi
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#endif
+1 -7
Ver Arquivo
@@ -652,13 +652,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
if (extruder_plan.prev_extruder_standby_temp)
{ // turn off previous extruder
constexpr bool wait = false;
double prev_extruder_temp = *extruder_plan.prev_extruder_standby_temp;
int prev_layer_nr = (extruder_plan_idx == 0)? layer_nr - 1 : layer_nr;
if (prev_layer_nr == storage.max_print_height_per_extruder[prev_extruder])
{
prev_extruder_temp = 0; // TODO ? should there be a setting for extruder_off_temperature ?
}
gcode.writeTemperatureCommand(prev_extruder, prev_extruder_temp, wait);
gcode.writeTemperatureCommand(prev_extruder, *extruder_plan.prev_extruder_standby_temp, wait);
}
}
gcode.writeFanCommand(extruder_plan.getFanSpeed());
-2
Ver Arquivo
@@ -2,9 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
#include <signal.h>
#if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
#include <execinfo.h>
+12 -2
Ver Arquivo
@@ -9,14 +9,20 @@ void carveMultipleVolumes(std::vector<Slicer*> &volumes)
for (unsigned int volume_1_idx = 0; volume_1_idx < volumes.size(); volume_1_idx++)
{
Slicer& volume_1 = *volumes[volume_1_idx];
if (volume_1.mesh->getSettingBoolean("infill_mesh"))
if (volume_1.mesh->getSettingBoolean("infill_mesh")
|| volume_1.mesh->getSettingBoolean("anti_overhang_mesh")
|| volume_1.mesh->getSettingBoolean("support_mesh")
)
{
continue;
}
for (unsigned int volume_2_idx = 0; volume_2_idx < volume_1_idx; volume_2_idx++)
{
Slicer& volume_2 = *volumes[volume_2_idx];
if (volume_2.mesh->getSettingBoolean("infill_mesh"))
if (volume_2.mesh->getSettingBoolean("infill_mesh")
|| volume_2.mesh->getSettingBoolean("anti_overhang_mesh")
|| volume_2.mesh->getSettingBoolean("support_mesh")
)
{
continue;
}
@@ -48,6 +54,8 @@ void generateMultipleVolumesOverlap(std::vector<Slicer*> &volumes)
{
int overlap = volume->mesh->getSettingInMicrons("multiple_mesh_overlap");
if (volume->mesh->getSettingBoolean("infill_mesh")
|| volume->mesh->getSettingBoolean("anti_overhang_mesh")
|| volume->mesh->getSettingBoolean("support_mesh")
|| overlap == 0)
{
continue;
@@ -60,6 +68,8 @@ void generateMultipleVolumesOverlap(std::vector<Slicer*> &volumes)
for (Slicer* other_volume : volumes)
{
if (other_volume->mesh->getSettingBoolean("infill_mesh")
|| other_volume->mesh->getSettingBoolean("anti_overhang_mesh")
|| other_volume->mesh->getSettingBoolean("support_mesh")
|| !other_volume->mesh->getAABB().hit(aabb)
|| other_volume == volume
)
+2 -2
Ver Arquivo
@@ -13,7 +13,7 @@ namespace cura {
*/
void PathOrderOptimizer::optimize()
{
bool *picked = static_cast<bool*>(alloca(sizeof(bool) * polygons.size()));
bool picked[polygons.size()];
memset(picked, false, sizeof(bool) * polygons.size());/// initialized as falses
for (PolygonRef poly : polygons) /// find closest point to initial starting point within each polygon +initialize picked
@@ -154,7 +154,7 @@ void LineOrderOptimizer::optimize()
{
int gridSize = 5000; // the size of the cells in the hash grid. TODO
SparsePointGridInclusive<unsigned int> line_bucket_grid(gridSize);
bool *picked = static_cast<bool*>(alloca(sizeof(bool) * polygons.size()));
bool picked[polygons.size()];
memset(picked, false, sizeof(bool) * polygons.size());/// initialized as falses
for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++) /// find closest point to initial starting point within each polygon +initialize picked
+1 -17
Ver Arquivo
@@ -3,11 +3,7 @@
#include <sstream>
#include <iostream> // debug IO
#ifndef WIN32
#include <libgen.h> // dirname
#else
extern char *dirname(char *path);
#endif
#include <string>
#include <cstring> // strtok (split string using delimiters) strcpy
#include <fstream> // ifstream (to see if file exists)
@@ -155,7 +151,7 @@ int SettingRegistry::loadJSONsettings(std::string filename, SettingsBase* settin
if (err) { return err; }
{ // add parent folder to search paths
char *filename_cstr = static_cast<char*>(alloca(filename.size()));
char filename_cstr[filename.size()];
std::strcpy(filename_cstr, filename.c_str()); // copy the string because dirname(.) changes the input string!!!
std::string folder_name = std::string(dirname(filename_cstr));
search_paths.emplace(folder_name);
@@ -385,15 +381,3 @@ void SettingRegistry::_loadSettingValues(SettingConfig* config, const rapidjson:
}
}//namespace cura
#ifdef WIN32
#include <windows.h>
char *dirname(char *path)
{
static char folder_name[MAX_PATH + 1], *p;
GetFullPathNameA(path, _countof(folder_name), folder_name, &p);
p[-1] = 0;
return folder_name;
}
#endif
-4
Ver Arquivo
@@ -6,11 +6,7 @@
#include <stdio.h> // for file output
#include <sstream>
#include <iostream> // debug IO
#ifndef WIN32
#include <libgen.h> // dirname
#else
extern char *dirname(char *path);
#endif
#include <string>
#include <algorithm> // find_if
#include <regex> // regex_search
+1 -1
Ver Arquivo
@@ -180,7 +180,7 @@ bool SettingsBaseVirtual::getSettingBoolean(std::string key) const
return true;
if (value == "yes")
return true;
if (value == "true" || value == "True") //Python uses "True"
if (value == "true" or value == "True") //Python uses "True"
return true;
int num = atoi(value.c_str());
return num != 0;
+2 -11
Ver Arquivo
@@ -162,17 +162,8 @@ void generateInfill(int layerNr, SliceMeshStorage& mesh, const int innermost_wal
}
}
infill.removeSmallAreas(MIN_AREA_SIZE);
Polygons final_infill = infill.offset(infill_skin_overlap);
if (mesh.getSettingBoolean("infill_hollow"))
{
part.print_outline = part.print_outline.difference(final_infill);
}
else
{
part.infill_area = final_infill;
}
part.infill_area = infill.offset(infill_skin_overlap);
}
}
+2 -2
Ver Arquivo
@@ -105,7 +105,7 @@ SliceDataStorage::SliceDataStorage(MeshGroup* meshgroup) : SettingsMessenger(mes
raft_surface_config(PrintFeatureType::SupportInterface),
support_config(PrintFeatureType::Support),
support_skin_config(PrintFeatureType::SupportInterface),
max_print_height_second_to_last_extruder(-1)
max_object_height_second_to_last_extruder(-1)
{
}
@@ -142,7 +142,7 @@ Polygons SliceDataStorage::getLayerOutlines(int layer_nr, bool include_helper_pa
{
for (const SliceMeshStorage& mesh : meshes)
{
if (mesh.getSettingBoolean("infill_mesh"))
if (mesh.getSettingBoolean("infill_mesh") || mesh.getSettingBoolean("anti_overhang_mesh"))
{
continue;
}
+3 -4
Ver Arquivo
@@ -125,6 +125,8 @@ class SupportLayer
public:
Polygons supportAreas; //!< normal support areas
Polygons skin; //!< the support areas which are to be printed as denser roofs and/or bottoms. Note that the roof/bottom areas and support areas should be mutually exclusive.
Polygons support_mesh; //!< Areas from support meshes
Polygons anti_overhang; //!< Areas where no overhang should be detected.
};
class SupportStorage
@@ -195,10 +197,7 @@ public:
Polygons skirt_brim[MAX_EXTRUDERS]; //!< Skirt and brim polygons per extruder, ordered from inner to outer polygons.
Polygons raftOutline; //Storage for the outline of the raft. Will be filled with lines when the GCode is generated.
int max_print_height_second_to_last_extruder; //!< Used in multi-extrusion: the layer number beyond which all models are printed with the same extruder
std::vector<int> max_print_height_per_extruder; //!< For each extruder the highest layer number at which it is used.
std::vector<size_t> max_print_height_order; //!< Ordered indices into max_print_height_per_extruder: back() will return the extruder number with the highest print height.
int max_object_height_second_to_last_extruder; //!< Used in multi-extrusion: the layer number beyond which all models are printed with the same extruder
PrimeTower primeTower;
std::vector<Polygons> oozeShield; //oozeShield per layer
+58 -11
Ver Arquivo
@@ -11,8 +11,28 @@
namespace cura
{
void AreaSupport::handleSupportMeshes(SliceDataStorage& storage, std::vector<Slicer*>& volumes)
{
assert(volumes.size() == storage.meshes.size() && "There should be the same amount of meshes as sliced meshes!");
for (unsigned int mesh_idx = 0; mesh_idx < volumes.size(); mesh_idx++)
{
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
if (!mesh.getSettingBoolean("support_mesh"))
{
continue;
}
Slicer& slicer = *volumes[mesh_idx];
for (unsigned int layer_nr = 0; layer_nr < slicer.layers.size(); layer_nr++)
{
SlicerLayer& slicer_layer = slicer.layers[layer_nr];
SupportLayer& support_layer = storage.support.supportLayers[layer_nr];
// support_layer.
}
}
}
Polygons AreaSupport::join(Polygons& supportLayer_up, Polygons& supportLayer_this, int64_t supportJoinDistance, int64_t smoothing_distance, int max_smoothing_angle, bool conical_support, int64_t conical_support_offset, int64_t conical_smallest_breadth)
{
Polygons joined;
@@ -65,14 +85,32 @@ Polygons AreaSupport::join(Polygons& supportLayer_up, Polygons& supportLayer_thi
void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int layer_count)
{
int max_layer_nr_support_mesh_filled;
for (max_layer_nr_support_mesh_filled = storage.support.supportLayers.size() - 1; max_layer_nr_support_mesh_filled >= 0; max_layer_nr_support_mesh_filled--)
{
const SupportLayer& support_layer = storage.support.supportLayers[max_layer_nr_support_mesh_filled];
if (support_layer.supportAreas.size() > 0)
{
break;
}
}
storage.support.layer_nr_max_filled_layer = std::max(storage.support.layer_nr_max_filled_layer, (int)max_layer_nr_support_mesh_filled);
for (int layer_nr = 0; layer_nr < max_layer_nr_support_mesh_filled; layer_nr++)
{
SupportLayer& support_layer = storage.support.supportLayers[max_layer_nr_support_mesh_filled];
support_layer.support_mesh = support_layer.support_mesh.unionPolygons();
}
// initialization of supportAreasPerLayer
for (unsigned int layer_idx = 0; layer_idx < layer_count ; layer_idx++)
storage.support.supportLayers.emplace_back();
for(unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++)
if (layer_count > storage.support.supportLayers.size())
{ // there might alsready be anti_overhang_area data in the supportLayers
storage.support.supportLayers.resize(layer_count);
}
for (unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++)
{
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
if (mesh.getSettingBoolean("infill_mesh"))
if (mesh.getSettingBoolean("infill_mesh") || mesh.getSettingBoolean("anti_overhang_mesh"))
{
continue;
}
@@ -247,8 +285,9 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int m
{ // join with support from layer up
supportLayer_this = AreaSupport::join(supportLayer_last, supportLayer_this, join_distance, smoothing_distance, max_smoothing_angle, conical_support, conical_support_offset, conical_smallest_breadth);
}
supportLayer_this = supportLayer_this.unionPolygons(storage.support.supportLayers[layer_idx].support_mesh);
// move up from model
if (layerZdistanceBottom > 0 && layer_idx >= layerZdistanceBottom)
{
@@ -349,6 +388,9 @@ std::pair<Polygons, Polygons> AreaSupport::computeBasicAndFullOverhang(const Sli
Polygons supportLayer_supported = supportLayer_supporter.offset(max_dist_from_lower_layer);
Polygons basic_overhang = supportLayer_supportee.difference(supportLayer_supported);
const SupportLayer& support_layer = storage.support.supportLayers[layer_idx];
basic_overhang = basic_overhang.difference(support_layer.anti_overhang);
// Polygons support_extension = basic_overhang.offset(max_dist_from_lower_layer);
// support_extension = support_extension.intersection(supportLayer_supported);
// support_extension = support_extension.intersection(supportLayer_supportee);
@@ -388,12 +430,17 @@ void AreaSupport::detectOverhangPoints(
if (part_poly.size() > 0)
{
Polygons part_poly_recomputed = part_poly.difference(storage.support.supportLayers[layer_idx].anti_overhang);
if (part_poly_recomputed.size() == 0)
{
continue;
}
if (overhang_points.size() > 0 && overhang_points.back().first == layer_idx)
overhang_points.back().second.push_back(part_poly);
overhang_points.back().second.push_back(part_poly_recomputed);
else
{
std::vector<Polygons> small_part_polys;
small_part_polys.push_back(part_poly);
small_part_polys.push_back(part_poly_recomputed);
overhang_points.emplace_back<std::pair<int, std::vector<Polygons>>>(std::make_pair(layer_idx, small_part_polys));
}
}
+8 -1
Ver Arquivo
@@ -5,11 +5,19 @@
#include "sliceDataStorage.h"
#include "MeshGroup.h"
#include "commandSocket.h"
#include "slicer.h"
namespace cura {
class AreaSupport {
public:
/*!
* Move support mesh from slicer data into the support storage
*
* \param[out] storage Where to store the support areas
* \param volumes All sliced volumes in the meshgroup
*/
static void handleSupportMeshes(SliceDataStorage& storage, std::vector<Slicer*>& volumes);
/*!
* Generate the support areas and support skin areas for all models.
@@ -17,7 +25,6 @@ public:
* \param layer_count total number of layers
*/
static void generateSupportAreas(SliceDataStorage& storage, unsigned int layer_count);
private:
/*!
* Generate support polygons over all layers for one object.
-47
Ver Arquivo
@@ -1,47 +0,0 @@
/** Copyright (C) 2016 Ultimaker - Released under terms of the AGPLv3 License */
#ifndef UTILS_ALGORITHM_H
#define UTILS_ALGORITHM_H
#include <algorithm>
#include <vector>
#include <functional>
#include <numeric>
// extensions to algorithm.h from the standard library
namespace cura
{
/*!
* Get the order of a vector: the sorted indices of a vector
*
* {1.6, 1.8, 1.7} returns {1, 3, 2} meaning {in[1], in[3], in[2]} is a sorted
* vector
*
* Thanks to Lukasz Wiklendt
*
* \param in The vector for which to get the order
* \return An ordered vector of indices into \p in
*/
template<typename T>
std::vector<size_t> order(const std::vector<T> &in)
{
// initialize original index locations
std::vector<size_t> order(in.size());
std::iota(order.begin(), order.end(), 0); // fill vector with 1, 2, 3,.. etc
// sort indexes based on comparing values in v
std::sort(order.begin(), order.end(),
[&in](size_t i1, size_t i2)
{
return in[i1] < in[i2];
}
);
return order;
}
} // namespace cura
#endif // UTILS_ALGORITHM_H
+5 -5
Ver Arquivo
@@ -2,14 +2,14 @@
#ifndef GETTIME_H
#define GETTIME_H
#ifdef WIN32
#ifdef __WIN32
#include <windows.h>
#else
#include <sys/time.h>
#ifdef USE_CPU_TIME
#include <sys/resource.h>
#endif
#include <sys/time.h>
#include <stddef.h>
#include <cassert>
#endif
@@ -18,9 +18,9 @@ namespace cura
{
static inline double getTime()
{
#ifdef WIN32
#ifdef __WIN32
return double(GetTickCount()) / 1000.0;
#else // not WIN32
#else // not __WIN32
#if USE_CPU_TIME // Use cpu usage time if available, otherwise wall clock time
struct rusage usage;
#ifdef DEBUG
@@ -38,7 +38,7 @@ static inline double getTime()
gettimeofday(&tv, nullptr);
return double(tv.tv_sec) + double(tv.tv_usec) / 1000000.0;
#endif // USE_CPU_TIME
#endif // WIN32
#endif // __WIN32
}
class TimeKeeper
+2 -2
Ver Arquivo
@@ -119,9 +119,9 @@ unsigned int Polygons::findInside(Point p, bool border_result)
return false;
}
int64_t *min_x = static_cast<int64_t*>(alloca(sizeof(int64_t) * size()));
int64_t min_x[size()];
std::fill_n(min_x, size(), std::numeric_limits<int64_t>::max()); // initialize with int.max
int *crossings = static_cast<int*>(alloca(sizeof(int) * size()));
int crossings[size()];
std::fill_n(crossings, size(), 0); // initialize with zeros
for (unsigned int poly_idx = 0; poly_idx < size(); poly_idx++)
+5 -31
Ver Arquivo
@@ -5,10 +5,6 @@
#include <cstdio> // sprintf
#include <sstream> // ostringstream
#include <cinttypes> // PRId64
#include "logoutput.h"
namespace cura
{
@@ -33,19 +29,8 @@ static inline int stringcasecompare(const char* a, const char* b)
*/
static inline void writeInt2mm(const int64_t coord, std::ostream& ss)
{
constexpr size_t buffer_size = 24;
char buffer[buffer_size];
int char_count = sprintf(buffer, "%" PRId64, coord); // convert int to string
#ifdef DEBUG
if (char_count + 1 >= int(buffer_size)) // + 1 for the null character
{
logError("Cannot write %ld to buffer of size %i", coord, buffer_size);
}
if (char_count < 0)
{
logError("Encoding error while writing %ld", coord);
}
#endif // DEBUG
char buffer[24];
int char_count = sprintf(buffer, "%ld", coord); // convert int to string
int end_pos = char_count; // the first character not to write any more
int trailing_zeros = 1;
while (trailing_zeros < 4 && buffer[char_count - trailing_zeros] == '0')
@@ -118,21 +103,10 @@ struct MMtoStream
*/
static inline void writeDoubleToStream(const unsigned int precision, const double coord, std::ostream& ss)
{
char format[5] = "%.xF"; // write a float with [x] digits after the dot
char format[5] = "%.xf"; // write a float with [x] digits after the dot
format[2] = '0' + precision; // set [x]
constexpr size_t buffer_size = 400;
char buffer[buffer_size];
int char_count = sprintf(buffer, format, coord);
#ifdef DEBUG
if (char_count + 1 >= int(buffer_size)) // + 1 for the null character
{
logError("Cannot write %f to buffer of size %i", coord, buffer_size);
}
if (char_count < 0)
{
logError("Encoding error while writing %f", coord);
}
#endif // DEBUG
char buffer[24];
int char_count = snprintf(buffer, 24, format, coord);
if (char_count <= 0)
{
return;
-112
Ver Arquivo
@@ -3,12 +3,10 @@
#include "StringTest.h"
#include <iomanip>
#include <sstream> // ostringstream
#include <../src/utils/intpoint.h>
#include <../src/utils/string.h>
namespace cura
{
CPPUNIT_TEST_SUITE_REGISTRATION(StringTest);
@@ -71,25 +69,13 @@ void StringTest::writeInt2mmTest123456789()
{
writeInt2mmAssert(123456789);
}
void StringTest::writeInt2mmTestMax()
{
writeInt2mmAssert(std::numeric_limits<int64_t>::max() / 1001); // divide by 1001, because MM2INT first converts to int and then multiplies by 1000, which causes overflow for the highest integer.
}
void StringTest::writeInt2mmAssert(int64_t in)
{
std::ostringstream ss;
writeInt2mm(in, ss);
ss.flush();
std::string str = ss.str();
if (!ss.good())
{
char buffer[200];
sprintf(buffer, "The integer %ld was printed as '%s' which was a bad string!", in, str.c_str());
CPPUNIT_ASSERT_MESSAGE(std::string(buffer), false);
}
int64_t out = MM2INT(strtod(str.c_str(), nullptr));
char buffer[200];
@@ -98,102 +84,4 @@ void StringTest::writeInt2mmAssert(int64_t in)
}
void StringTest::writeDoubleToStreamTest10000Negative()
{
writeDoubleToStreamAssert(-10.000);
}
void StringTest::writeDoubleToStreamTest1000Negative()
{
writeDoubleToStreamAssert(-1.000);
}
void StringTest::writeDoubleToStreamTest100Negative()
{
writeDoubleToStreamAssert(-.100);
}
void StringTest::writeDoubleToStreamTest10Negative()
{
writeDoubleToStreamAssert(-.010);
}
void StringTest::writeDoubleToStreamTest1Negative()
{
writeDoubleToStreamAssert(-.001);
}
void StringTest::writeDoubleToStreamTest0()
{
writeDoubleToStreamAssert(0.000);
}
void StringTest::writeDoubleToStreamTest1()
{
writeDoubleToStreamAssert(.001);
}
void StringTest::writeDoubleToStreamTest10()
{
writeDoubleToStreamAssert(.010);
}
void StringTest::writeDoubleToStreamTest100()
{
writeDoubleToStreamAssert(.100);
}
void StringTest::writeDoubleToStreamTest1000()
{
writeDoubleToStreamAssert(1.000);
}
void StringTest::writeDoubleToStreamTest10000()
{
writeDoubleToStreamAssert(10.000);
}
void StringTest::writeDoubleToStreamTest123456789()
{
writeDoubleToStreamAssert(123456.789);
}
void StringTest::writeDoubleToStreamTestMin()
{
writeDoubleToStreamAssert(std::numeric_limits<double>::min());
}
void StringTest::writeDoubleToStreamTestMax()
{
writeDoubleToStreamAssert(std::numeric_limits<double>::max());
}
void StringTest::writeDoubleToStreamTestLowest()
{
writeDoubleToStreamAssert(std::numeric_limits<double>::lowest());
}
void StringTest::writeDoubleToStreamTestLowestNeg()
{
writeDoubleToStreamAssert(-std::numeric_limits<double>::lowest());
}
void StringTest::writeDoubleToStreamTestLow()
{
writeDoubleToStreamAssert(0.00000001d);
}
void StringTest::writeDoubleToStreamAssert(double in, unsigned int precision)
{
std::ostringstream ss;
writeDoubleToStream(precision, in, ss);
ss.flush();
std::string str = ss.str();
if (!ss.good())
{
char buffer[8000];
sprintf(buffer, "The double %f was printed as '%s' which was a bad string!", in, str.c_str());
CPPUNIT_ASSERT_MESSAGE(std::string(buffer), false);
}
double out = strtod(str.c_str(), nullptr);
std::ostringstream in_ss;
in_ss << std::fixed << std::setprecision(precision) << in;
std::string in_str = in_ss.str();
double in_reinterpreted = strtod(in_str.c_str(), nullptr);
char buffer[8000];
sprintf(buffer, "The double %f was printed as '%s' which was interpreted as %f rather than %f!", in, str.c_str(), out, in_reinterpreted);
if (in_reinterpreted != out) std::cerr << buffer << "\n";
CPPUNIT_ASSERT_MESSAGE(std::string(buffer), in_reinterpreted == out);
}
}
-49
Ver Arquivo
@@ -25,25 +25,6 @@ class StringTest : public CppUnit::TestFixture
CPPUNIT_TEST(writeInt2mmTest1000);
CPPUNIT_TEST(writeInt2mmTest10000);
CPPUNIT_TEST(writeInt2mmTest123456789);
CPPUNIT_TEST(writeInt2mmTestMax);
CPPUNIT_TEST(writeDoubleToStreamTest10000Negative);
CPPUNIT_TEST(writeDoubleToStreamTest1000Negative);
CPPUNIT_TEST(writeDoubleToStreamTest100Negative);
CPPUNIT_TEST(writeDoubleToStreamTest10Negative);
CPPUNIT_TEST(writeDoubleToStreamTest1Negative);
CPPUNIT_TEST(writeDoubleToStreamTest0);
CPPUNIT_TEST(writeDoubleToStreamTest1);
CPPUNIT_TEST(writeDoubleToStreamTest10);
CPPUNIT_TEST(writeDoubleToStreamTest100);
CPPUNIT_TEST(writeDoubleToStreamTest1000);
CPPUNIT_TEST(writeDoubleToStreamTest10000);
CPPUNIT_TEST(writeDoubleToStreamTest123456789);
CPPUNIT_TEST(writeDoubleToStreamTestMin);
CPPUNIT_TEST(writeDoubleToStreamTestMax);
CPPUNIT_TEST(writeDoubleToStreamTestLowest);
CPPUNIT_TEST(writeDoubleToStreamTestLowestNeg);
CPPUNIT_TEST(writeDoubleToStreamTestLow);
CPPUNIT_TEST_SUITE_END();
public:
@@ -76,25 +57,6 @@ public:
void writeInt2mmTest1000();
void writeInt2mmTest10000();
void writeInt2mmTest123456789();
void writeInt2mmTestMax();
void writeDoubleToStreamTest10000Negative();
void writeDoubleToStreamTest1000Negative();
void writeDoubleToStreamTest100Negative();
void writeDoubleToStreamTest10Negative();
void writeDoubleToStreamTest1Negative();
void writeDoubleToStreamTest0();
void writeDoubleToStreamTest1();
void writeDoubleToStreamTest10();
void writeDoubleToStreamTest100();
void writeDoubleToStreamTest1000();
void writeDoubleToStreamTest10000();
void writeDoubleToStreamTest123456789();
void writeDoubleToStreamTestMin();
void writeDoubleToStreamTestMax();
void writeDoubleToStreamTestLowest();
void writeDoubleToStreamTestLowestNeg();
void writeDoubleToStreamTestLow();
private:
@@ -107,17 +69,6 @@ private:
* \param in the integer to check
*/
void writeInt2mmAssert(int64_t in);
/*!
* \brief Performs the actual assertion for the getDist2FromLineSegmentTest.
*
* This is essentially a parameterised version of all unit tests pertaining
* to the writeInt2mm tests.
*
* \param in the double to check
* \param precision the (maximum) number of digits after the decimal mark to print
*/
void writeDoubleToStreamAssert(double in, unsigned int precision = 4);
};
}