Comparar commits
13 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 693921d644 | |||
| dbe6269262 | |||
| ac2bbd9c39 | |||
| 9d56baba41 | |||
| 24c9384253 | |||
| 00041da2df | |||
| 3c7c352bfc | |||
| 66e6375942 | |||
| 8d3f66c2cb | |||
| 1fd540c231 | |||
| ac799dd00e | |||
| 699406b044 | |||
| 2f3333e87c |
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,9 +2,7 @@
|
||||
|
||||
#include <cmath> // sqrt
|
||||
#include <fstream> // debug IO
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "progress/Progress.h"
|
||||
#include "weaveDataStorage.h"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <string> // stoi
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -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,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
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário