Comparar commits

...

52 Commits

Autor SHA1 Mensagem Data
Tim Kuipers a3b85c0362 fix: remove polygon complexities introduced by texture offsets (CURA-1371) 2016-12-14 18:02:21 +01:00
Tim Kuipers 0084d16c98 fix: TextureProcessor::dist_left_over wasn't computed properly if p0p1 was too short (CURA-1371)
this resulted in out-of-image texture coordinates

refactor: factor out processSegmentBumpMap out of processBumpMap (CURA-1371)

for readibility.
2016-12-14 17:17:24 +01:00
Tim Kuipers 9ede9ea524 fix: Material: round to nearest pixel (CURA-1371)
also some refactor has been done which is handy for (linear) interpolation, but I don't know whether I should even do this / give the option for it.
2016-12-14 17:06:19 +01:00
Tim Kuipers e4d2161de4 lil refactor: inlined Material::getPixelCoords (CURA-1371) 2016-12-14 15:06:37 +01:00
Tim Kuipers 0a824aac3c fix: account for snapping of slice segments for texture retrieval (CURA-1371) 2016-12-14 14:57:30 +01:00
Tim Kuipers cbcd5df2f7 feat: ColoutUsage setting enum (CURA-1371) 2016-12-14 14:55:59 +01:00
Tim Kuipers 31493500f1 debug: output image to std::cerr (CURA-1371) 2016-12-14 14:34:29 +01:00
Tim Kuipers c3689e0b58 feat: more color options in Material (CURA-1371) 2016-12-14 13:34:05 +01:00
Tim Kuipers d3e455290a fix: use image loader library instead of buggy readBMP function (CURA-1371) 2016-12-14 12:43:37 +01:00
Tim Kuipers 66ad67693e fix: obj loading ignores normals and empty lines (CURA-1371) 2016-12-13 14:21:21 +01:00
Tim Kuipers 43d4097556 refactor: process ==> processBumpMap (CURA-1371) 2016-12-13 14:20:31 +01:00
Tim Kuipers 1d030b4251 lil fix 2016-12-13 14:18:24 +01:00
Tim Kuipers d74fdf2f6c fix: added corner point handling to mesh texture offset (CURA-1371) 2016-12-13 14:18:24 +01:00
Tim Kuipers a4dc1733e8 fix: material coordinates were out of bounds (inverted) (CURA-1371) 2016-12-13 14:18:24 +01:00
Tim Kuipers a6fad000e4 fix: getFaceEdgeMatCoord converted to MM implicitly (CURA-1371) 2016-12-13 14:18:24 +01:00
Tim Kuipers 0274330a09 feat: actual texture to offset computation (still buggy) (CURA-1371)
not all material coordinates seem to be recorded
material coordinates seem always around the same value
2016-12-13 14:18:04 +01:00
Tim Kuipers 119c7e6a3d fix: ambiguous overload in FPoint (CURA-1371) 2016-12-13 13:59:53 +01:00
Tim Kuipers e74ee27256 lil (CURA-1371) 2016-12-13 13:59:53 +01:00
Tim Kuipers 4288a75d0f feat: TextureProcessor for polygons (CURA-1371) 2016-12-13 13:58:58 +01:00
Tim Kuipers ada75a04a0 fix: SlicerSegment hashing fix (CURA-1371) 2016-12-13 11:57:22 +01:00
Tim Kuipers f9ec748e91 feat: segment to material mapping (CURA-1371) 2016-12-13 11:57:22 +01:00
Tim Kuipers 3b59c79bf4 fix: obj parsing fixes and output (CURA-1371) 2016-12-13 11:50:04 +01:00
Tim Kuipers 2cb637b79b lil: SlicerSegment operator== (CURA-1371) 2016-12-13 11:50:04 +01:00
Tim Kuipers dff6595f27 refactor: registerFaceSlice result in MatSegment (CURA-1371) 2016-12-13 11:49:22 +01:00
Tim Kuipers aac3975e5d refactor: factored out child classes from TexturedMesh into MatCoord and FPoint (CURA-1371) 2016-12-13 11:39:02 +01:00
Tim Kuipers f69d070dd4 refactor: factored out child classes from TexturedMesh into MatCoord and FPoint (CURA-1371) 2016-12-13 11:37:48 +01:00
Tim Kuipers d28798ee52 fix: getFaceEdgeMatCoord should result in MatCoord (CURA-1371) 2016-12-13 11:37:48 +01:00
Tim Kuipers 1760d6b8ed fix: obj texture coordinates didn't get loaded (CURA-1371) 2016-12-13 11:37:48 +01:00
Tim Kuipers 80b3436075 refactor: moved slicer related files into slicer folder (CURA-1371) 2016-12-13 11:32:55 +01:00
Tim Kuipers 8ca0fc4cb0 refactor: moved slicer classes to separate files (CURA-1371) 2016-12-13 11:24:43 +01:00
Tim Kuipers 53c4fd28bf feat: mesh.registerFaceSlice for textured meshes (CURA-1371) 2016-12-13 10:40:07 +01:00
Tim Kuipers 56e8f8b10c refactor: send order information to project2D (slicer) (CURA-1371) 2016-12-12 19:16:37 +01:00
Tim Kuipers 1fa6298455 feat: small optimization in slicer (CURA-1371) 2016-12-12 18:53:59 +01:00
Tim Kuipers e7e0fe4050 feat: TexturedMesh.getFaceEdgeMatCoord (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers a7e0d49235 quick hack: sdfsdsgdgsda 2016-12-12 18:00:20 +01:00
Tim Kuipers 8e85c00452 refactor: material coords double ==> float; feat: TexturedMesh.getMatCoord (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers 96a4fe1725 fix: lil int casting thing (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers 13fe966db3 feat: retrieve color from material (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers 2da5b4960a fix: use updated material in obj file (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers 00d87b089b feat: load material image (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers 9ec30d8168 feat: loading of mtl (obj) (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers cb21c325f6 fix: support obj relative indexing (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers 35c2d018a5 fix: made obj loading robust against not having texture data (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers a9f749b4de fix: load obj file into a TexturedMesh (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers 4cecf7b8e3 fix: TexturedMesh contructor (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers d661a31041 fix: delete mesh if it didn't load properly (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers f65b270d2a fix: TexturedMesh.addFace wasn't finished yet (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers de85a67f28 feat: let mesh.addFace return whether it actually inserted a face (CURA-1371) 2016-12-12 18:00:20 +01:00
Tim Kuipers 65e9da693d feat: preliminary work for textured meshes (CURA-1371)
basic file structure and functions
2016-12-12 18:00:20 +01:00
Tim Kuipers 921333a7bc refactor: meshgroup.meshes became a vector of pointers (CURA-1371)
This to support future objects inheriting from Mesh
2016-12-12 17:59:26 +01:00
Tim Kuipers bb9aa2280d feat: support basic obj files (non-textured) (CURA-1371) 2016-12-12 17:38:39 +01:00
Tim Kuipers a38d2fa31e added functionality to Mesh to load obj files 2016-12-12 17:38:39 +01:00
41 arquivos alterados com 8560 adições e 278 exclusões
+9 -3
Ver Arquivo
@@ -59,12 +59,12 @@ set(engine_SRCS # Except main.cpp.
src/gcodePlanner.cpp
src/infill.cpp
src/WallsComputation.cpp
src/layerPart.cpp
src/LayerPlanBuffer.cpp
src/Material.cpp
src/MaterialBase.cpp
src/MergeInfillLines.cpp
src/mesh.cpp
src/MeshGroup.cpp
src/multiVolumes.cpp
src/pathOrderOptimizer.cpp
src/Preheat.cpp
src/PrimeTower.cpp
@@ -72,9 +72,10 @@ set(engine_SRCS # Except main.cpp.
src/skin.cpp
src/SkirtBrim.cpp
src/sliceDataStorage.cpp
src/slicer.cpp
src/support.cpp
src/timeEstimate.cpp
src/TexturedMesh.cpp
src/TextureProcessor.cpp
src/WallsComputation.cpp
src/wallOverlap.cpp
src/Weaver.cpp
@@ -87,6 +88,11 @@ set(engine_SRCS # Except main.cpp.
src/infill/ZigzagConnectorProcessorNoEndPieces.cpp
src/infill/SubDivCube.cpp
src/slicer/LayerPart.cpp
src/slicer/MultiVolumes.cpp
src/slicer/SlicerLayer.cpp
src/slicer/Slicer.cpp
src/pathPlanning/Comb.cpp
src/pathPlanning/LinePolygonsCrossings.cpp
src/pathPlanning/TimeMaterialEstimates.cpp
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
#ifndef CONICAL_OVERHANG_H
#define CONICAL_OVERHANG_H
#include "slicer.h"
#include "slicer/Slicer.h"
namespace cura {
+1 -1
Ver Arquivo
@@ -698,7 +698,7 @@ std::vector<unsigned int> FffGcodeWriter::calculateMeshOrder(SliceDataStorage& s
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
if (mesh.getSettingAsIndex("extruder_nr") == extruder_nr)
{
Mesh& mesh_data = storage.meshgroup->meshes[mesh_idx];
Mesh& mesh_data = *storage.meshgroup->meshes[mesh_idx];
Point3 middle = (mesh_data.getAABB().min + mesh_data.getAABB().max) / 2;
mesh_idx_order_optimizer.addItem(Point(middle.x, middle.y), mesh_idx);
}
+12 -10
Ver Arquivo
@@ -4,14 +4,15 @@
#include <map> // multimap (ordered map allowing duplicate keys)
#include "utils/math.h"
#include "slicer/Slicer.h"
#include "utils/algorithm.h"
#include "slicer.h"
#include "utils/gettime.h"
#include "utils/logoutput.h"
#include "MeshGroup.h"
#include "support.h"
#include "multiVolumes.h"
#include "layerPart.h"
#include "slicer/MultiVolumes.h"
#include "slicer/LayerPart.h"
#include "TextureProcessor.h"
#include "WallsComputation.h"
#include "SkirtBrim.h"
#include "skin.h"
@@ -88,7 +89,7 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
std::vector<Slicer*> slicerList;
for(unsigned int mesh_idx = 0; mesh_idx < meshgroup->meshes.size(); mesh_idx++)
{
Mesh& mesh = meshgroup->meshes[mesh_idx];
Mesh& mesh = *meshgroup->meshes[mesh_idx];
Slicer* slicer = new Slicer(&mesh, initial_slice_z, layer_thickness, slice_layer_count, mesh.getSettingBoolean("meshfix_keep_open_polygons"), mesh.getSettingBoolean("meshfix_extensive_stitching"));
slicerList.push_back(slicer);
/*
@@ -107,7 +108,7 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
for(unsigned int meshIdx=0; meshIdx < slicerList.size(); meshIdx++)
{
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
Mesh& mesh = *storage.meshgroup->meshes[meshIdx];
if (mesh.getSettingBoolean("conical_overhang_enabled") && !mesh.getSettingBoolean("anti_overhang_mesh"))
{
ConicalOverhang::apply(slicerList[meshIdx], mesh.getSettingInAngleRadians("conical_overhang_angle"), layer_thickness);
@@ -116,6 +117,7 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
Progress::messageProgressStage(Progress::Stage::PARTS, &timeKeeper);
if (storage.getSettingBoolean("carve_multiple_volumes"))
{
carveMultipleVolumes(slicerList, storage.getSettingBoolean("alternate_carve_order"));
@@ -125,7 +127,7 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
storage.print_layer_count = 0;
for (unsigned int meshIdx = 0; meshIdx < slicerList.size(); meshIdx++)
{
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
Mesh& mesh = *storage.meshgroup->meshes[meshIdx];
Slicer* slicer = slicerList[meshIdx];
if (!mesh.getSettingBoolean("anti_overhang_mesh") && !mesh.getSettingBoolean("infill_mesh"))
{
@@ -138,10 +140,10 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
for (unsigned int meshIdx = 0; meshIdx < slicerList.size(); meshIdx++)
{
Slicer* slicer = slicerList[meshIdx];
Mesh& mesh = storage.meshgroup->meshes[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
storage.meshes.emplace_back(meshgroup->meshes[meshIdx], slicer->layers.size()); // new mesh in storage had settings from the Mesh
SliceMeshStorage& meshStorage = storage.meshes.back();
if (mesh.getSettingBoolean("anti_overhang_mesh"))
@@ -357,8 +359,8 @@ void FffPolygonGenerator::processBasicWallsSkinInfill(SliceDataStorage& storage,
SliceMeshStorage& other_mesh = storage.meshes[other_mesh_idx];
if (other_mesh.getSettingBoolean("infill_mesh"))
{
AABB3D aabb = storage.meshgroup->meshes[mesh_idx].getAABB();
AABB3D other_aabb = storage.meshgroup->meshes[other_mesh_idx].getAABB();
AABB3D aabb = storage.meshgroup->meshes[mesh_idx]->getAABB();
AABB3D other_aabb = storage.meshgroup->meshes[other_mesh_idx]->getAABB();
if (aabb.hit(other_aabb))
{
process_infill = true;
+3 -3
Ver Arquivo
@@ -38,7 +38,7 @@ std::string FffProcessor::getAllSettingsString(MeshGroup& meshgroup, bool first_
}
for (unsigned int mesh_idx = 0; mesh_idx < meshgroup.meshes.size(); mesh_idx++)
{
Mesh& mesh = meshgroup.meshes[mesh_idx];
Mesh& mesh = *meshgroup.meshes[mesh_idx];
sstream << " -e" << mesh.getSettingAsIndex("extruder_nr") << " -l \"" << mesh_idx << "\"" << mesh.getAllLocalSettingsString();
}
sstream << "\n";
@@ -58,9 +58,9 @@ bool FffProcessor::processMeshGroup(MeshGroup* meshgroup)
gcode_writer.setParent(meshgroup);
bool empty = true;
for (Mesh& mesh : meshgroup->meshes)
for (Mesh* mesh : meshgroup->meshes)
{
if (!mesh.getSettingBoolean("infill_mesh") && !mesh.getSettingBoolean("anti_overhang_mesh"))
if (!mesh->getSettingBoolean("infill_mesh") && !mesh->getSettingBoolean("anti_overhang_mesh"))
{
empty = false;
}
+27
Ver Arquivo
@@ -0,0 +1,27 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef MAT_COORD_H
#define MAT_COORD_H
#include "utils/FPoint.h"
namespace cura
{
/*!
* Coordinates in a specific texture bitmap
*/
struct MatCoord
{
FPoint coords;
int mat_id; //!< Material id
MatCoord() //!< non-initializing constructor
{}
MatCoord(FPoint coords, int mat_id) //!< constructor
: coords(coords)
, mat_id(mat_id)
{}
};
} // namespace cura
#endif // MAT_COORD_H
+27
Ver Arquivo
@@ -0,0 +1,27 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef MAT_SEGMENT_H
#define MAT_SEGMENT_H
#include "MatCoord.h"
namespace cura
{
/*!
* Coordinates in a specific texture bitmap
*/
struct MatSegment
{
MatCoord start;
MatCoord end;
MatSegment() //!< non-initializing constructor
{}
MatSegment(MatCoord start, MatCoord end)
: start(start)
, end(end)
{}
};
} // namespace cura
#endif // MAT_SEGMENT_H
+143
Ver Arquivo
@@ -0,0 +1,143 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#include <limits> // numeric limits
#include <algorithm> // min max
#include <iostream>
#include <cassert>
#include "Material.h"
namespace cura
{
Material::Material()
: data(nullptr)
, width(0)
, height(0)
, depth(0)
{
}
void Material::setData(unsigned char* data)
{
this->data = data;
}
void Material::setDimensions(unsigned int width, unsigned int height, unsigned int depth)
{
this->width = width;
this->height = height;
this->depth = depth;
}
float Material::getColor(float x, float y, ColourUsage color) const
{
assert(x >= 0.0f && x <= 1.0f);
assert(y >= 0.0f && y <= 1.0f);
switch (color)
{
case ColourUsage::RED:
case ColourUsage::GREEN:
case ColourUsage::BLUE:
case ColourUsage::ALPHA:
{
assert((int)color >= 0 && (unsigned int)color < depth && "Z out of bounds!");
return getColorData(x, y, (unsigned int) color);
}
case ColourUsage::GREY:
default:
{
float r = getColorData(x, y, (unsigned int) ColourUsage::RED);
float g = getColorData(x, y, (unsigned int) ColourUsage::GREEN);
float b = getColorData(x, y, (unsigned int) ColourUsage::BLUE);
return (r + g + b) / 3.0;
}
}
}
float Material::getColorData(float x, float y, unsigned int z) const
{
unsigned int x_idx = (unsigned int) (x * (width - 1) + 0.5);
assert(x_idx >= 0 && x_idx < width && "requested X is out of bounds!");
unsigned int y_idx = (unsigned int) (y * (height - 1) + 0.5);
assert(y_idx >= 0 && y_idx < height && "requested Y is out of bounds!");
unsigned char col = data[(y_idx * width + x_idx) * depth + z];
return (float) col / std::numeric_limits<unsigned char>::max();
}
void Material::debugOutput(bool dw) const
{
std::cerr << "\nImage size: " << width << " x " << height << " (" << depth << "channels)\n";
std::cerr << '+';
for (unsigned int i = 0; i < width; i++)
{
std::cerr << ((dw)? "--" : "-");
}
std::cerr << "+\n";
for (unsigned int y = 0; y < height; y++)
{
std::cerr << "|";
for (unsigned int x = 0; x < width; x++)
{
int val = (data[(y*width+x)*depth] * 10 / 256);
switch (val)
{
case 0:
std::cerr << ((dw)? " " : " ");
break;
case 1:
std::cerr << ((dw)? ".." : ".");
break;
case 2:
std::cerr << ((dw)? ",," : ",");
break;
case 3:
std::cerr << ((dw)? "::" : ":");
break;
case 4:
std::cerr << ((dw)? ";;" : ";");
break;
case 5:
std::cerr << ((dw)? "++" : "+");
break;
case 6:
std::cerr << ((dw)? "░░" : "");
break;
case 7:
std::cerr << ((dw)? "▒▒" : "");
break;
case 8:
std::cerr << ((dw)? "▓▓" : "");
break;
default:
if (val > 8)
{
std::cerr << ((dw)? "██" : "");
}
else
{
std::cerr << ((dw)? " " : " ");
}
}
}
std::cerr << "|\n";
}
std::cerr << '+';
for (unsigned int i = 0; i < width; i++)
{
std::cerr << ((dw)? "--" : "-");
}
std::cerr << "+\n";
}
} // namespace cura
+67
Ver Arquivo
@@ -0,0 +1,67 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef MATERIAL_H
#define MATERIAL_H
#include "settings/settings.h" // ColourUsage
namespace cura
{
/*!
* The material used in a texture.
*
* This class just holds the image data and has some nice utility functions.
*/
class Material
{
public:
/*!
* non-initializing constructor
*/
Material();
/*!
* Set the pixel data of the image
* \param data pointer to the array of data in RGBA, left-to-right, top-to-bottom
*/
void setData(unsigned char* data);
/*!
* Set the dimensions of the image
* \param width The horizontal length of the imnage
* \param height The vertical length of the imnage
* \param depth The number of color channels
*/
void setDimensions(unsigned int width, unsigned int height, unsigned int depth);
/*!
* get the color value at a particular place in the image
*
* \param x place in the horizontal direction left to right (value between zero and one)
* \param y place in the vertical direction top to bottom (value between zero and one)
* \param color The color channel to check
* \return a value between zero and one
*/
float getColor(float x, float y, ColourUsage color) const;
/*!
* print out something which looks like the picture through std::cerr
* \param double_width Whether to double each character being written, so that the width is visually similar to the height of each pixel.
*/
void debugOutput(bool double_width = true) const;
protected:
unsigned char* data; //!< pixel data in rgb-row-first (or bgr-row first ?)
unsigned int width, height, depth; //!< image dimensions
/*!
* Get a color value from the data
* \param x place in the horizontal direction left to right (value between zero and one)
* \param y place in the vertical direction top to bottom (value between zero and one)
* \return the color data (0-256)
*/
float getColorData(float x, float y, unsigned int z) const;
};
} // namespace cura
#endif // MATERIAL_H
+42
Ver Arquivo
@@ -0,0 +1,42 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#include "MaterialBase.h"
namespace cura
{
Material* MaterialBase::add(std::string name)
{
name_to_mat_idx[name] = materials.size();
materials.emplace_back();
return &materials.back();
}
const Material* MaterialBase::getMat(unsigned int id) const
{
if (id < materials.size())
{
return &materials[id];
}
else
{
return nullptr;
}
}
int MaterialBase::getMatId(std::string name) const
{
auto it = name_to_mat_idx.find(name);
if (it == name_to_mat_idx.end())
{
return -1;
}
else
{
return it->second;
}
}
} // namespace cura
+27
Ver Arquivo
@@ -0,0 +1,27 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef MATERIAL_BASE_H
#define MATERIAL_BASE_H
#include <unordered_map>
#include <string>
#include <vector>
#include "Material.h"
namespace cura
{
class MaterialBase
{
public:
int getMatId(std::string name) const;
Material* add(std::string name);
const Material* getMat(unsigned int id) const;
protected:
std::unordered_map<std::string, int> name_to_mat_idx;
std::vector<Material> materials;
};
} // namespace cura
#endif // MATERIAL_BASE_H
+183 -22
Ver Arquivo
@@ -3,6 +3,9 @@
#include <strings.h>
#include <stdio.h>
#define STB_IMAGE_IMPLEMENTATION // needed in order to enable the implementation of libs/std_image.h
#include "stb/stb_image.h"
#include "MeshGroup.h"
#include "utils/gettime.h"
#include "utils/logoutput.h"
@@ -25,6 +28,10 @@ void* fgets_(char* ptr, size_t len, FILE* f)
*ptr = '\0';
return ptr;
}
else if (*ptr =='\0')
{
return ptr;
}
ptr++;
len--;
}
@@ -45,6 +52,10 @@ MeshGroup::~MeshGroup()
delete extruders[extruder];
}
}
for (Mesh* mesh : meshes)
{
delete mesh;
}
}
int MeshGroup::getExtruderCount() const
@@ -90,10 +101,10 @@ Point3 MeshGroup::min() const
{
return Point3(0, 0, 0);
}
Point3 ret = meshes[0].min();
for(unsigned int i=1; i<meshes.size(); i++)
Point3 ret = meshes[0]->min();
for (unsigned int i = 1; i < meshes.size(); i++)
{
Point3 v = meshes[i].min();
Point3 v = meshes[i]->min();
ret.x = std::min(ret.x, v.x);
ret.y = std::min(ret.y, v.y);
ret.z = std::min(ret.z, v.z);
@@ -107,10 +118,10 @@ Point3 MeshGroup::max() const
{
return Point3(0, 0, 0);
}
Point3 ret = meshes[0].max();
for(unsigned int i=1; i<meshes.size(); i++)
Point3 ret = meshes[0]->max();
for (unsigned int i = 1; i < meshes.size(); i++)
{
Point3 v = meshes[i].max();
Point3 v = meshes[i]->max();
ret.x = std::max(ret.x, v.x);
ret.y = std::max(ret.y, v.y);
ret.z = std::max(ret.z, v.z);
@@ -120,9 +131,9 @@ Point3 MeshGroup::max() const
void MeshGroup::clear()
{
for(Mesh& m : meshes)
for (Mesh* m : meshes)
{
m.clear();
m->clear();
}
}
@@ -140,9 +151,9 @@ void MeshGroup::finalize()
continue;
}
for (const Mesh& mesh : meshes)
for (const Mesh* mesh : meshes)
{
if (mesh.getSettingBoolean("support_enable")
if (mesh->getSettingBoolean("support_enable")
&& (
getSettingAsIndex("support_infill_extruder_nr") == extruder_nr
|| getSettingAsIndex("support_extruder_nr_layer_0") == extruder_nr
@@ -156,13 +167,13 @@ void MeshGroup::finalize()
}
}
for (const Mesh& mesh : meshes)
for (const Mesh* mesh : meshes)
{
if (!mesh.getSettingBoolean("anti_overhang_mesh")
&& !mesh.getSettingBoolean("support_mesh")
if (!mesh->getSettingBoolean("anti_overhang_mesh")
&& !mesh->getSettingBoolean("support_mesh")
)
{
getExtruderTrain(mesh.getSettingAsIndex("extruder_nr"))->setIsUsed(true);
getExtruderTrain(mesh->getSettingAsIndex("extruder_nr"))->setIsUsed(true);
}
}
@@ -175,17 +186,17 @@ void MeshGroup::finalize()
}
// If a mesh position was given, put the mesh at this position in 3D space.
for(Mesh& mesh : meshes)
for (Mesh* mesh : meshes)
{
Point3 mesh_offset(mesh.getSettingInMicrons("mesh_position_x"), mesh.getSettingInMicrons("mesh_position_y"), mesh.getSettingInMicrons("mesh_position_z"));
if (mesh.getSettingBoolean("center_object"))
Point3 mesh_offset(mesh->getSettingInMicrons("mesh_position_x"), mesh->getSettingInMicrons("mesh_position_y"), mesh->getSettingInMicrons("mesh_position_z"));
if (mesh->getSettingBoolean("center_object"))
{
Point3 object_min = mesh.min();
Point3 object_max = mesh.max();
Point3 object_min = mesh->min();
Point3 object_max = mesh->max();
Point3 object_size = object_max - object_min;
mesh_offset += Point3(-object_min.x - object_size.x / 2, -object_min.y - object_size.y / 2, -object_min.z);
}
mesh.offset(mesh_offset + meshgroup_offset);
mesh->offset(mesh_offset + meshgroup_offset);
}
}
@@ -329,6 +340,138 @@ bool loadMeshSTL(Mesh* mesh, const char* filename, const FMatrix3x3& matrix)
return loadMeshSTL_binary(mesh, filename, matrix);
}
void loadMatImage(Material* mat, const char* filename)
{
int width;
int height;
int depth;
// in RGBA order
unsigned char* data = stbi_load(filename, &width, &height, &depth, 0);
if (data)
{
mat->setData(data);
mat->setDimensions(width, height, depth);
}
else
{
logError("Cannot load image %s.", filename);
}
}
void loadMaterialBase(TexturedMesh* mesh, const char* filename)
{
FILE* f = fopen(filename, "rt");
if (f == nullptr)
{
logError("ERROR: Couldn't load MTL file %s.\n", filename);
return;
}
char buffer[1024];
char mat_name [100];
char mat_file [100];
char map_type [10];
Material* last_mat = nullptr;
while(fgets_(buffer, sizeof(buffer), f))
{
if (buffer[0] == '#')
{
continue;
}
if (sscanf(buffer, "map_%s %s", map_type, mat_file) == 2 // we don't care what type of map it specifies (currently)
|| sscanf(buffer, "bump %s", mat_file) == 1
|| sscanf(buffer, "disp %s", mat_file) == 1
|| sscanf(buffer, "decal %s", mat_file) == 1
|| sscanf(buffer, "refl %s", mat_file) == 1
)
{
std::string parent_dir = std::string(filename).substr(0, std::string(filename).find_last_of("/\\"));
std::string mtl_file = parent_dir + "/" + mat_file;
if (last_mat)
{
loadMatImage(last_mat, mtl_file.c_str());
}
}
else if (sscanf(buffer, "newmtl %s", mat_name) == 1)
{
last_mat = mesh->addMaterial(mat_name);
}
}
fclose(f);
}
bool loadMeshOBJ(TexturedMesh* mesh, const char* filename, const FMatrix3x3& matrix)
{
FILE* f = fopen(filename, "rt");
if (f == nullptr)
{
return false;
}
char buffer[1024];
FPoint3 vertex;
Point3 vertex_indices;
float texture_x;
float texture_y;
float temp;
char face_index_buffer_1 [100];
char face_index_buffer_2 [100];
char face_index_buffer_3 [100];
char str_buffer [100];
while(fgets_(buffer, sizeof(buffer), f))
{
if (buffer[0] == '#')
{
continue;
}
if (sscanf(buffer, "v %f %f %f", &vertex.x, &vertex.y, &vertex.z) == 3)
{
Point3 v = matrix.apply(vertex);
mesh->addVertex(v);
}
else if (sscanf(buffer, "vt %f %f", &texture_x, &texture_y) == 2)
{
mesh->addTextureCoord(texture_x, texture_y);
}
else if (sscanf(buffer, "f %s %s %s", face_index_buffer_1, face_index_buffer_2, face_index_buffer_3) == 3)
{
int normal_vector_index; // unused
Point3 texture_indices(0, 0, 0); // becomes -1 if no texture data supplied
int n_scanned_1 = sscanf(face_index_buffer_1, "%d/%d/%d", &vertex_indices.x, &texture_indices.x, &normal_vector_index);
int n_scanned_2 = sscanf(face_index_buffer_2, "%d/%d/%d", &vertex_indices.y, &texture_indices.y, &normal_vector_index);
int n_scanned_3 = sscanf(face_index_buffer_3, "%d/%d/%d", &vertex_indices.z, &texture_indices.z, &normal_vector_index);
if (n_scanned_1 > 0 && n_scanned_2 > 0 && n_scanned_3 > 0)
{
mesh->addFace(vertex_indices.x - 1, vertex_indices.y - 1, vertex_indices.z - 1, texture_indices.x - 1, texture_indices.y - 1, texture_indices.z - 1);
// obj files count vertex indices starting from 1!
}
}
else if (sscanf(buffer, "mtllib %s", str_buffer) == 1)
{
std::string parent_dir = std::string(filename).substr(0, std::string(filename).find_last_of("/\\"));
std::string mtl_file = parent_dir + "/" + str_buffer;
loadMaterialBase(mesh, mtl_file.c_str());
}
else if (sscanf(buffer, "usemtl %s", str_buffer) == 1)
{
mesh->setMaterial(str_buffer);
}
else if (sscanf(buffer, "vn %f %f %f", &temp, &temp, &temp) == 3)
{
// do nothing
}
else if (buffer[0] == '\0')
{
// empty line, do nothing
}
else
{
logError("Cannot parse line \"%s\"\n", buffer);
}
}
fclose(f);
mesh->finish();
return true;
}
bool loadMeshIntoMeshGroup(MeshGroup* meshgroup, const char* filename, const FMatrix3x3& transformation, SettingsBaseVirtual* object_parent_settings)
{
TimeKeeper load_timer;
@@ -336,14 +479,32 @@ bool loadMeshIntoMeshGroup(MeshGroup* meshgroup, const char* filename, const FMa
const char* ext = strrchr(filename, '.');
if (ext && (strcmp(ext, ".stl") == 0 || strcmp(ext, ".STL") == 0))
{
Mesh mesh = object_parent_settings ? Mesh(object_parent_settings) : Mesh(meshgroup); //If we have object_parent_settings, use them as parent settings. Otherwise, just use meshgroup.
if(loadMeshSTL(&mesh,filename,transformation)) //Load it! If successful...
Mesh* mesh = new Mesh(object_parent_settings ? object_parent_settings : meshgroup); //If we have object_parent_settings, use them as parent settings. Otherwise, just use meshgroup.
if (loadMeshSTL(mesh,filename,transformation)) //Load it! If successful...
{
meshgroup->meshes.push_back(mesh);
log("loading '%s' took %.3f seconds\n",filename,load_timer.restart());
return true;
}
else
{
delete mesh;
}
}
else if (ext && (strcmp(ext, ".obj") == 0 || strcmp(ext, ".OBJ") == 0))
{
TexturedMesh* mesh = new TexturedMesh(object_parent_settings ? object_parent_settings : meshgroup); //If we have object_parent_settings, use them as parent settings. Otherwise, just use meshgroup.
if (loadMeshOBJ(mesh,filename,transformation)) //Load it! If successful...
{
meshgroup->meshes.push_back(mesh);
return true;
}
else
{
delete mesh;
}
}
return false;
}
+2 -1
Ver Arquivo
@@ -4,6 +4,7 @@
#include "utils/NoCopy.h"
#include "mesh.h"
#include "TexturedMesh.h"
#include "ExtruderTrain.h"
namespace cura
@@ -35,7 +36,7 @@ public:
const ExtruderTrain* getExtruderTrain(unsigned int extruder_nr) const;
std::vector<Mesh> meshes;
std::vector<Mesh*> meshes;
Point3 min() const; //! minimal corner of bounding box
Point3 max() const; //! maximal corner of bounding box
+141
Ver Arquivo
@@ -0,0 +1,141 @@
#include "TextureProcessor.h"
#include <algorithm> // swap
#include "utils/optional.h"
#include "slicer/SlicerSegment.h"
namespace cura
{
#define POINT_DIST 400
#define AMPLITUDE 3000
#define EXTRA_OFFSET 3000
/*
void TextureProcessor::process(std::vector< Slicer* >& slicer_list)
{
for (Slicer* slicer : slicer_list)
{
for (SlicerLayer& layer : slicer->layers)
{
process(slicer->mesh, layer);
}
}
}
*/
void TextureProcessor::processSegmentBumpMap(const Mesh* mesh, const SlicerSegment& slicer_segment, const MatSegment& mat, const Point p0, const Point p1, coord_t& dist_left_over, PolygonRef result)
{
MatCoord mat_start = mat.start;
MatCoord mat_end = mat.end;
if (vSize2(slicer_segment.start - p0) > vSize2(slicer_segment.start - p1))
{
std::swap(mat_start, mat_end);
}
Point p0p1 = p1 - p0;
int64_t p0p1_size = vSize(p0p1);
if (dist_left_over >= p0p1_size)
{
dist_left_over -= p0p1_size;
return;
}
Point perp_to_p0p1 = turn90CCW(p0p1);
int64_t dist_last_point = -1; // p0p1_size * 2 - dist_left_over; // so that p0p1_size - dist_last_point evaulates to dist_left_over - p0p1_size
// TODO: move start point (which was already moved last iteration
for (int64_t p0pa_dist = dist_left_over; p0pa_dist < p0p1_size; p0pa_dist += POINT_DIST)
{
assert(p0pa_dist >= 0);
assert(p0pa_dist <= p0p1_size);
MatCoord mat_coord_now = mat_start;
mat_coord_now.coords = mat_start.coords + (mat_end.coords - mat_start.coords) * p0pa_dist / p0p1_size;
float val = mesh->getColor(mat_coord_now, ColourUsage::GREY);
int offset = val * (AMPLITUDE * 2) - AMPLITUDE + EXTRA_OFFSET;
Point fuzz = normal(perp_to_p0p1, offset);
Point pa = p0 + normal(p0p1, p0pa_dist) - fuzz;
result.add(pa);
dist_last_point = p0pa_dist;
}
// TODO: move end point as well
float val = mesh->getColor(mat_end, ColourUsage::GREY);
int r = val * (AMPLITUDE * 2) - AMPLITUDE + EXTRA_OFFSET;
Point fuzz = normal(perp_to_p0p1, r);
result.emplace_back(p1 - fuzz);
assert(dist_last_point >= 0 && "above loop should have run at least once!");
assert(p0p1_size > dist_last_point);
dist_left_over = p0p1_size - dist_last_point;
assert(dist_left_over <= POINT_DIST);
}
void TextureProcessor::processBumpMap(const Mesh* mesh, SlicerLayer& layer)
{
Polygons results;
for (PolygonRef poly : layer.polygons)
{
// generate points in between p0 and p1
PolygonRef result = results.newPoly();
coord_t dist_left_over = (POINT_DIST / 2); // the distance to be traversed on the line before making the first new point
Point* p0 = &poly.back();
for (Point& p1 : poly)
{ // 'a' is the (next) new point between p0 and p1
if (*p0 == p1)
{
continue;
}
SlicerSegment segment(*p0, p1);
std::optional<std::pair<SlicerSegment, MatSegment>> best_mat_segment_it;
coord_t best_dist_score = std::numeric_limits<coord_t>::max();
for (std::unordered_map<SlicerSegment, MatSegment>::iterator it = layer.segment_to_material_segment.begin(); it != layer.segment_to_material_segment.end(); ++it)
{
const SlicerSegment& sliced_segment = it->first;
coord_t dist_score = std::min(
vSize2(sliced_segment.start - segment.start) + vSize2(sliced_segment.end - segment.end)
, vSize2(sliced_segment.end - segment.start) + vSize2(sliced_segment.start - segment.end)
);
if (dist_score < best_dist_score)
{
best_dist_score = dist_score;
best_mat_segment_it = *it;
}
}
if (best_dist_score < 30 * 30) // TODO: magic value of 0.03mm for total stitching distance > should be something like SlicerLayer.cpp::largest_neglected_gap_second_phase (?)
{
assert(best_mat_segment_it);
processSegmentBumpMap(mesh, best_mat_segment_it->first, best_mat_segment_it->second, *p0, p1, dist_left_over, result);
}
else
{
result.emplace_back(p1);
}
p0 = &p1;
}
while (result.size() < 3 )
{
unsigned int point_idx = poly.size() - 2;
result.add(poly[point_idx]);
if (point_idx == 0) { break; }
point_idx--;
}
if (result.size() < 3)
{
result.clear();
for (Point& p : poly)
result.add(p);
}
}
// a negative offset on two sides of a corner, may introduce complexities in the model which should be removed:
// ^↘
// ^ ↘
// <<<<<<<<^<<<< should become <<<<<<<<
// ^ ^
// ^ ^
// ^ ^
layer.polygons = results.removeComplexParts();
}
}//namespace cura
+25
Ver Arquivo
@@ -0,0 +1,25 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef TEXTURE_PROCESSOR_H
#define TEXTURE_PROCESSOR_H
#include <vector>
#include "slicer/Slicer.h"
#include "mesh.h"
namespace cura
{
class TextureProcessor
{
public:
// static void process(std::vector<Slicer*>& slicer_list);
static void processBumpMap(const Mesh* mesh, SlicerLayer& layer);
protected:
static void processSegmentBumpMap(const Mesh* mesh, const SlicerSegment& slicer_segment, const MatSegment& mat, const Point p0, const Point p1, coord_t& dist_left_over, PolygonRef result);
};
} // namespace cura
#endif // TEXTURE_PROCESSOR_H
+137
Ver Arquivo
@@ -0,0 +1,137 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#include "TexturedMesh.h"
#include <cassert>
#include "utils/logoutput.h"
namespace cura
{
TexturedMesh::TexturedMesh(SettingsBaseVirtual* sb)
: Mesh(sb)
, current_mat(-1) // not set yet
{
}
void TexturedMesh::addTextureCoord(float x, float y)
{
texture_coords.emplace_back(x, y);
}
void TexturedMesh::addFace(int vi0, int vi1, int vi2, int ti0, int ti1, int ti2)
{
if (vi0 < -1)
{
vi0 = Mesh::faces.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (vi1 < -1)
{
vi1 = Mesh::faces.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (vi2 < -1)
{
vi2 = Mesh::faces.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (ti0 < -1)
{
ti0 = texture_coords.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (ti1 < -1)
{
ti1 = texture_coords.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (ti2 < -1)
{
ti2 = texture_coords.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
bool made_new_face = Mesh::addFace(vi0, vi1, vi2);
if (made_new_face)
{
face_texture_indices.emplace_back(ti0, ti1, ti2, current_mat);
assert(Mesh::faces.size() == face_texture_indices.size());
}
}
bool TexturedMesh::setMaterial(std::string name)
{
current_mat = material_base.getMatId(name);
return current_mat >= 0;
}
Material* TexturedMesh::addMaterial(std::__cxx11::string name)
{
return material_base.add(name);
}
bool TexturedMesh::getFaceEdgeMatCoord(unsigned int face_idx, int64_t z, unsigned int p0_idx, unsigned int p1_idx, MatCoord& result) const
{
if (face_idx >= face_texture_indices.size() || face_idx >= faces.size())
{
return false;
}
FaceTextureCoordIndices texture_idxs = face_texture_indices[face_idx];
if (texture_idxs.index[0] < 0 || texture_idxs.index[1] < 0 || texture_idxs.index[2] < 0 || texture_idxs.mat_id < 0)
{
return false;
}
const MeshFace& face = faces[face_idx];
Point3 p0(vertices[face.vertex_index[p0_idx]].p);
Point3 p1(vertices[face.vertex_index[p1_idx]].p);
float dzp0 = z - p0.z;
float dp0p1 = p1.z - p0.z;
if (dzp0 * dp0p1 < 0)
{ // z doesn't lie between p0 and p1
return false;
}
if (dzp0 == 0)
{ // edge is not cut by horizontal plane!
return false;
}
float ratio = INT2MM(dzp0) / INT2MM(dp0p1);
FPoint t0 = texture_coords[texture_idxs.index[p0_idx]];
FPoint t1 = texture_coords[texture_idxs.index[p1_idx]];
result.mat_id = texture_idxs.mat_id;
result.coords.x = t0.x + (t1.x - t0.x) * ratio;
result.coords.y = t0.y + (t1.y - t0.y) * ratio;
if (result.coords.x > 1.001 || result.coords.x < -0.001 || result.coords.y > 1.001 || result.coords.y < -0.001)
{
logError("WARNING: wapping material to outside image!");
}
return true;
}
bool TexturedMesh::registerFaceSlice(unsigned int face_idx, unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, Point segment_start, Point segment_end, MatSegment& result) const
{
if (!getFaceEdgeMatCoord(face_idx, z, idx_shared, idx_first, result.start))
{
return false;
}
if (!getFaceEdgeMatCoord(face_idx, z, idx_shared, idx_second, result.end))
{
return false;
}
return true;
}
float TexturedMesh::getColor(MatCoord bitmap_coord, ColourUsage color) const
{
const Material* mat = material_base.getMat(bitmap_coord.mat_id);
if (mat)
{
return mat->getColor(bitmap_coord.coords.x, bitmap_coord.coords.y, color);
}
else
{
return 0.0f;
}
}
} // namespace cura
+78
Ver Arquivo
@@ -0,0 +1,78 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef TEXTURED_MESH_H
#define TEXTURED_MESH_H
#include <vector>
#include <string>
#include "MaterialBase.h"
#include "mesh.h"
#include "utils/intpoint.h"
#include "MatSegment.h"
namespace cura
{
/*!
* A mesh with bitmap textures to it.
*
* material coordinates are defined separately, and can be reused for different bitmap textures
*/
class TexturedMesh : public Mesh
{
public:
TexturedMesh(SettingsBaseVirtual* sb);
/*!
*
*/
struct FaceTextureCoordIndices
{
int index[3]; //!< indices into texture_coords or -1 if no texture data available
int mat_id; //!< Material id
FaceTextureCoordIndices(int i1, int i2, int i3, int mat_id)
: mat_id(mat_id)
{
index[0] = i1;
index[1] = i2;
index[2] = i3;
}
};
void addTextureCoord(float x, float y);
void addFace(int vi0, int vi1, int vi2, int ti0, int ti1, int ti2);
using Mesh::addFace; // otherwise above addFace would shadow the parent addFace
bool setMaterial(std::string name); //!< set the material to be used in the comming data to be loaded
Material* addMaterial(std::string name);
virtual bool registerFaceSlice(unsigned int face_idx, unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, Point segment_start, Point segment_end, MatSegment& result) const;
protected:
std::vector<FPoint> texture_coords; //!< all texture coordinates by all faces
std::vector<FaceTextureCoordIndices> face_texture_indices; //!< for each face the corresponding texture coordinates in TexturedMesh::texture_coords
// TODO clean up above lists when super class clear() is called
// TODO when to clean up below material base?
MaterialBase material_base;
/*!
* Get the material coordinate corresponding to the point on a plane cutting a given edge of the face.
* \param face_idx The face for which to get the material coord
* \param z The z of the horizontal plane cutting the face
* \param p0_idx The index into the first vert of the edge
* \param p1_idx The index into the second vert of the edge
* \param result The resulting material Coordinates
* \return Whether a Material coordinate is defined at the given location
*/
bool getFaceEdgeMatCoord(unsigned int face_idx, int64_t z, unsigned int p0_idx, unsigned int p1_idx, MatCoord& result) const;
virtual float getColor(MatCoord bitmap_coord, ColourUsage color) const;
private:
int current_mat; //!< material currently used in loading the face material info
};
} // namespace cura
#endif // TEXTURED_MESH_H
+2 -2
Ver Arquivo
@@ -23,9 +23,9 @@ void Weaver::weave(MeshGroup* meshgroup)
std::vector<cura::Slicer*> slicerList;
for(Mesh& mesh : meshgroup->meshes)
for (Mesh* mesh : meshgroup->meshes)
{
cura::Slicer* slicer = new cura::Slicer(&mesh, initial_layer_thickness, connectionHeight, layer_count, mesh.getSettingBoolean("meshfix_keep_open_polygons"), mesh.getSettingBoolean("meshfix_extensive_stitching"));
cura::Slicer* slicer = new cura::Slicer(mesh, initial_layer_thickness, connectionHeight, layer_count, mesh->getSettingBoolean("meshfix_keep_open_polygons"), mesh->getSettingBoolean("meshfix_extensive_stitching"));
slicerList.push_back(slicer);
}
+1 -1
Ver Arquivo
@@ -6,7 +6,7 @@
#include "settings/settings.h"
#include "MeshGroup.h"
#include "slicer.h"
#include "slicer/Slicer.h"
#include "utils/NoCopy.h"
#include "utils/polygon.h"
+1 -1
Ver Arquivo
@@ -11,7 +11,7 @@
#include "settings/settings.h"
#include "MeshGroup.h"
#include "slicer.h"
#include "slicer/Slicer.h"
#include "utils/polygon.h"
#include "Weaver.h"
+4 -4
Ver Arquivo
@@ -346,9 +346,9 @@ void CommandSocket::connect(const std::string& ip, int port)
continue;
}
const ExtruderTrain* settings_base = meshgroup->getExtruderTrain(extruder_nr); //The extruder train that the setting should fall back to.
for (Mesh& mesh : meshgroup->meshes)
for (Mesh* mesh : meshgroup->meshes)
{
mesh.setSettingInheritBase(setting_extruder.name(), *settings_base);
mesh->setSettingInheritBase(setting_extruder.name(), *settings_base);
}
}
}
@@ -455,8 +455,8 @@ void CommandSocket::handleObjectList(cura::proto::ObjectList* list, const google
}
SettingsBase* extruder_train = meshgroup->getExtruderTrain(extruder_train_nr);
meshgroup->meshes.push_back(extruder_train); //Construct a new mesh (with the corresponding extruder train as settings parent object) and put it into MeshGroup's mesh list.
Mesh& mesh = meshgroup->meshes.back();
meshgroup->meshes.push_back(new Mesh(extruder_train)); //Construct a new mesh (with the corresponding extruder train as settings parent object) and put it into MeshGroup's mesh list.
Mesh& mesh = *meshgroup->meshes.back();
for (int i = 0; i < face_count; ++i)
{
+8 -8
Ver Arquivo
@@ -52,13 +52,13 @@ void GCodeExport::preSetup(const MeshGroup* meshgroup)
extruder_count = meshgroup->getSettingAsCount("machine_extruder_count");
for (const Mesh& mesh : meshgroup->meshes)
for (const Mesh* mesh : meshgroup->meshes)
{
if (!mesh.getSettingBoolean("anti_overhang_mesh")
&& !mesh.getSettingBoolean("support_mesh")
if (!mesh->getSettingBoolean("anti_overhang_mesh")
&& !mesh->getSettingBoolean("support_mesh")
)
{
extruder_attr[mesh.getSettingAsIndex("extruder_nr")].is_used = true;
extruder_attr[mesh->getSettingAsIndex("extruder_nr")].is_used = true;
}
}
@@ -70,11 +70,11 @@ void GCodeExport::preSetup(const MeshGroup* meshgroup)
{
extruder_attr[extruder_nr].is_used = true;
}
for (const Mesh& mesh : meshgroup->meshes)
for (const Mesh* mesh : meshgroup->meshes)
{
if ((mesh.getSettingBoolean("support_enable") && mesh.getSettingBoolean("support_interface_enable") && meshgroup->getSettingAsIndex("support_interface_extruder_nr") == int(extruder_nr))
|| (mesh.getSettingBoolean("support_enable") && meshgroup->getSettingAsIndex("support_infill_extruder_nr") == int(extruder_nr))
|| (mesh.getSettingBoolean("support_enable") && meshgroup->getSettingAsIndex("support_extruder_nr_layer_0") == int(extruder_nr))
if ((mesh->getSettingBoolean("support_enable") && mesh->getSettingBoolean("support_interface_enable") && meshgroup->getSettingAsIndex("support_interface_extruder_nr") == int(extruder_nr))
|| (mesh->getSettingBoolean("support_enable") && meshgroup->getSettingAsIndex("support_infill_extruder_nr") == int(extruder_nr))
|| (mesh->getSettingBoolean("support_enable") && meshgroup->getSettingAsIndex("support_extruder_nr_layer_0") == int(extruder_nr))
)
{
extruder_attr[extruder_nr].is_used = true;
+1 -1
Ver Arquivo
@@ -210,7 +210,7 @@ void slice(int argc, char **argv)
}
else
{
last_settings_object = &(meshgroup->meshes.back()); // pointer is valid until a new object is added, so this is OK
last_settings_object = meshgroup->meshes.back();
}
break;
case 'o':
+33 -2
Ver Arquivo
@@ -19,12 +19,21 @@ Mesh::Mesh(SettingsBaseVirtual* parent)
{
}
void Mesh::addFace(Point3& v0, Point3& v1, Point3& v2)
bool Mesh::addFace(Point3& v0, Point3& v1, Point3& v2)
{
int vi0 = findIndexOfVertex(v0);
int vi1 = findIndexOfVertex(v1);
int vi2 = findIndexOfVertex(v2);
if (vi0 == vi1 || vi1 == vi2 || vi0 == vi2) return; // the face has two vertices which get assigned the same location. Don't add the face.
return addFace(vi0, vi1, vi2);
}
bool Mesh::addFace(int vi0, int vi1, int vi2)
{
if (vi0 == vi1 || vi1 == vi2 || vi0 == vi2)
{
// the face has two vertices which get assigned the same location. Don't add the face.
return false;
}
int idx = faces.size(); // index of face to be added
faces.emplace_back();
@@ -35,6 +44,8 @@ void Mesh::addFace(Point3& v0, Point3& v1, Point3& v2)
vertices[face.vertex_index[0]].connected_faces.push_back(idx);
vertices[face.vertex_index[1]].connected_faces.push_back(idx);
vertices[face.vertex_index[2]].connected_faces.push_back(idx);
return true;
}
void Mesh::clear()
@@ -81,6 +92,14 @@ void Mesh::expandXY(int64_t offset)
}
void Mesh::addVertex(const Point3& v)
{
uint32_t hash = pointHash(v);
vertex_hash_map[hash].push_back(vertices.size());
vertices.emplace_back(v);
aabb.include(v);
}
int Mesh::findIndexOfVertex(const Point3& v)
{
uint32_t hash = pointHash(v);
@@ -189,4 +208,16 @@ int Mesh::getFaceIdxWithPoints(int idx0, int idx1, int notFaceIdx, int notFaceVe
return bestIdx;
}
bool Mesh::registerFaceSlice(unsigned int face_idx, unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, Point segment_start, Point segment_end, MatSegment& result) const
{
// do nothing for a non-textured mesh
return false;
}
float Mesh::getColor(MatCoord, ColourUsage) const
{
return 0.0f;
}
}//namespace cura
+28 -1
Ver Arquivo
@@ -3,6 +3,7 @@
#include "settings/settings.h"
#include "utils/AABB3D.h"
#include "MatSegment.h"
namespace cura
{
@@ -65,7 +66,26 @@ public:
Mesh(SettingsBaseVirtual* parent); //!< initializes the settings
void addFace(Point3& v0, Point3& v1, Point3& v2); //!< add a face to the mesh without settings it's connected_faces.
virtual ~Mesh() {} //!< Destructor
/*!
* add a face to the mesh without settings it's connected_faces.
*
* Don't add a face when the surface is zero mm^2
*
* \return whether a face has been added
*/
bool addFace(Point3& v0, Point3& v1, Point3& v2);
/*!
* add a face to the mesh without settings it's connected_faces.
*
* Don't add a face when the surface is zero mm^2
*
* \return whether a face has been added
*/
bool addFace(int vi0, int vi1, int vi2);
void addVertex(const Point3& v);
void clear(); //!< clears all data
void finish(); //!< complete the model : set the connected_face_index fields of the faces.
@@ -86,6 +106,13 @@ public:
aabb.offset(offset);
}
/*!
* \return Whether a texture line segment has been created
*/
virtual bool registerFaceSlice(unsigned int face_idx, unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, Point segment_start, Point segment_end, MatSegment& result) const;
virtual float getColor(MatCoord bitmap_coord, ColourUsage color) const;
private:
int findIndexOfVertex(const Point3& v); //!< find index of vertex close to the given point, or create a new vertex and return its index.
+12
Ver Arquivo
@@ -177,6 +177,18 @@ enum class SupportDistPriority
Z_OVERRIDES_XY
};
/*!
* Which color(s) of a texture to use
*/
enum class ColourUsage
{
RED = 0,
GREEN = 1,
BLUE = 2,
ALPHA = 3,
GREY // use red, green and blue channels
};
#define MAX_EXTRUDERS 16
//Maximum number of infill layers that can be combined into a single infill extrusion area.
+21
Ver Arquivo
@@ -0,0 +1,21 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef SLICER_CLOSE_POLYGON_RESULT_H
#define SLICER_CLOSE_POLYGON_RESULT_H
#include "../utils/intpoint.h"
namespace cura
{
class ClosePolygonResult
{ //The result of trying to find a point on a closed polygon line. This gives back the point index, the polygon index, and the point of the connection.
//The line on which the point lays is between pointIdx-1 and pointIdx
public:
Point intersectionPoint;
int polygonIdx = -1;
unsigned int pointIdx = -1;
};
} // namespace cura
#endif // SLICER_CLOSE_POLYGON_RESULT_H
+22
Ver Arquivo
@@ -0,0 +1,22 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef SLICER_GAP_CLOSER_RESULT_H
#define SLICER_GAP_CLOSER_RESULT_H
#include "../utils/intpoint.h"
namespace cura
{
class GapCloserResult
{
public:
int64_t len = -1;
int polygonIdx = -1;
unsigned int pointIdxA = -1;
unsigned int pointIdxB = -1;
bool AtoB = false;
};
} // namespace cura
#endif // SLICER_GAP_CLOSER_RESULT_H
+4 -4
Ver Arquivo
@@ -1,10 +1,10 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include "layerPart.h"
#include "settings/settings.h"
#include "progress/Progress.h"
#include "LayerPart.h"
#include "../settings/settings.h"
#include "../progress/Progress.h"
#include "utils/SVG.h" // debug output
#include "../utils/SVG.h" // debug output
/*
The layer-part creation step is the first step in creating actual useful data for 3D printing.
+6 -6
Ver Arquivo
@@ -1,10 +1,10 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#ifndef LAYERPART_H
#define LAYERPART_H
#ifndef SLICER_LAYERPART_H
#define SLICER_LAYERPART_H
#include "sliceDataStorage.h"
#include "slicer.h"
#include "commandSocket.h"
#include "../sliceDataStorage.h"
#include "Slicer.h"
#include "../commandSocket.h"
/*
The layer-part creation step is the first step in creating actual useful data for 3D printing.
@@ -28,4 +28,4 @@ void layerparts2HTML(SliceDataStorage& mesh, const char* filename, bool all_laye
}//namespace cura
#endif//LAYERPART_H
#endif//SLICER_LAYERPART_H
@@ -1,4 +1,4 @@
#include "multiVolumes.h"
#include "MultiVolumes.h"
namespace cura
{
@@ -1,8 +1,8 @@
#ifndef MULTIVOLUMES_H
#define MULTIVOLUMES_H
#ifndef SLICER_MULTIVOLUMES_H
#define SLICER_MULTIVOLUMES_H
#include "sliceDataStorage.h"
#include "slicer.h"
#include "../sliceDataStorage.h"
#include "Slicer.h"
/* This file contains code to help fixing up and changing layers that are build from multiple volumes. */
namespace cura {
@@ -21,4 +21,4 @@ void generateMultipleVolumesOverlap(std::vector<Slicer*> &meshes);
}//namespace cura
#endif//MULTIVOLUMES_H
#endif//SLICER_MULTIVOLUMES_H
+147
Ver Arquivo
@@ -0,0 +1,147 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <stdio.h>
#include "../utils/gettime.h"
#include "../utils/logoutput.h"
#include "../MatCoord.h"
#include "Slicer.h"
namespace cura {
SlicerSegment Slicer::project2D(unsigned int face_idx, const Point3 p[3], unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, int32_t layer_nr)
{
const Point3& p0 = p[idx_shared];
const Point3& p1 = p[idx_first];
const Point3& p2 = p[idx_second];
SlicerSegment seg;
seg.start.X = interpolate(z, p0.z, p1.z, p0.x, p1.x);
seg.start.Y = interpolate(z, p0.z, p1.z, p0.y, p1.y);
seg.end .X = interpolate(z, p0.z, p2.z, p0.x, p2.x);
seg.end .Y = interpolate(z, p0.z, p2.z, p0.y, p2.y);
MatSegment mat_segment;
bool got_texture_coords = mesh->registerFaceSlice(face_idx, idx_shared, idx_first, idx_second, z, seg.start, seg.end, mat_segment);
if (got_texture_coords)
{
SlicerLayer& layer = layers[layer_nr];
layer.segment_to_material_segment.emplace(seg, mat_segment);
}
return seg;
}
Slicer::Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bool keep_none_closed, bool extensive_stitching)
: mesh(mesh)
{
assert(slice_layer_count > 0);
TimeKeeper slice_timer;
layers.resize(slice_layer_count);
for(int32_t layer_nr = 0; layer_nr < slice_layer_count; layer_nr++)
{
layers[layer_nr].z = initial + thickness * layer_nr;
}
for(unsigned int face_idx = 0; face_idx < mesh->faces.size(); face_idx++)
{
const MeshFace& face = mesh->faces[face_idx];
const MeshVertex& v0 = mesh->vertices[face.vertex_index[0]];
const MeshVertex& v1 = mesh->vertices[face.vertex_index[1]];
const MeshVertex& v2 = mesh->vertices[face.vertex_index[2]];
Point3 p[3] =
{ mesh->vertices[face.vertex_index[0]].p
, mesh->vertices[face.vertex_index[1]].p
, mesh->vertices[face.vertex_index[2]].p };
Point3& p0 = p[0];
Point3& p1 = p[1];
Point3& p2 = p[2];
int32_t minZ = p0.z;
int32_t maxZ = p0.z;
if (p1.z < minZ) minZ = p1.z;
if (p2.z < minZ) minZ = p2.z;
if (p1.z > maxZ) maxZ = p1.z;
if (p2.z > maxZ) maxZ = p2.z;
int32_t layer_max = (maxZ - initial) / thickness;
int32_t z = 0;
for (int32_t layer_nr = (minZ - initial + thickness - 1) / thickness; layer_nr < layer_max; layer_nr++) // + thickness - 1 to get the first layer above or at minZ
{
z = layer_nr * thickness + initial;
if (z < minZ) continue;
if (layer_nr < 0) continue;
SlicerSegment s;
s.endVertex = nullptr;
int end_edge_idx = -1;
if (p0.z < z && p1.z >= z && p2.z >= z)
{
s = project2D(face_idx, p, 0, 2, 1, z, layer_nr);
end_edge_idx = 0;
if (p1.z == z)
{
s.endVertex = &v1;
}
}
else if (p0.z > z && p1.z < z && p2.z < z)
{
s = project2D(face_idx, p, 0, 1, 2, z, layer_nr);
end_edge_idx = 2;
}
else if (p1.z < z && p0.z >= z && p2.z >= z)
{
s = project2D(face_idx, p, 1, 0, 2, z, layer_nr);
end_edge_idx = 1;
if (p2.z == z)
{
s.endVertex = &v2;
}
}
else if (p1.z > z && p0.z < z && p2.z < z)
{
s = project2D(face_idx, p, 1, 2, 0, z, layer_nr);
end_edge_idx = 0;
}
else if (p2.z < z && p1.z >= z && p0.z >= z)
{
s = project2D(face_idx, p, 2, 1, 0, z, layer_nr);
end_edge_idx = 2;
if (p0.z == z)
{
s.endVertex = &v0;
}
}
else if (p2.z > z && p1.z < z && p0.z < z)
{
s = project2D(face_idx, p, 2, 0, 1, z, layer_nr);
end_edge_idx = 1;
}
else
{
//Not all cases create a segment, because a point of a face could create just a dot, and two touching faces
// on the slice would create two segments
continue;
}
layers[layer_nr].face_idx_to_segment_idx.insert(std::make_pair(face_idx, layers[layer_nr].segments.size()));
s.faceIndex = face_idx;
s.endOtherFaceIdx = face.connected_face_index[end_edge_idx];
s.addedToPolygon = false;
layers[layer_nr].segments.push_back(s);
}
}
log("slice of mesh took %.3f seconds\n",slice_timer.restart());
for(unsigned int layer_nr=0; layer_nr<layers.size(); layer_nr++)
{
layers[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
}
mesh->expandXY(mesh->getSettingInMicrons("xy_offset"));
log("slice make polygons took %.3f seconds\n",slice_timer.restart());
}
}//namespace cura
+60
Ver Arquivo
@@ -0,0 +1,60 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#ifndef SLICER_SLICER_H
#define SLICER_SLICER_H
#include <queue>
#include "../mesh.h"
#include "../utils/polygon.h"
#include "SlicerSegment.h"
#include "ClosePolygonResult.h"
#include "SlicerLayer.h"
#include "../MatSegment.h"
/*
The Slicer creates layers of polygons from an optimized 3D model.
The result of the Slicer is a list of polygons without any order or structure.
*/
namespace cura {
class Slicer
{
public:
std::vector<SlicerLayer> layers;
const Mesh* mesh = nullptr; //!< The sliced mesh
Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bool keepNoneClosed, bool extensiveStitching);
/*!
* Linear interpolation
*
* Get the Y of a point with X \p x in the line through (\p x0, \p y0) and (\p x1, \p y1)
*
* \param p The face vertice locations in the order the vertices are given in the face
*/
int64_t interpolate(int64_t x, int64_t x0, int64_t x1, int64_t y0, int64_t y1) const
{
int64_t dx_01 = x1 - x0;
int64_t num = (y1 - y0) * (x - x0);
num += num > 0 ? dx_01/2 : -dx_01/2; // add in offset to round result
int64_t y = y0 + num / dx_01;
return y;
}
SlicerSegment project2D(unsigned int face_idx, const Point3 p[3], unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, int32_t layer_nr);
void dumpSegmentsToHTML(const char* filename);
};
}//namespace cura
#endif//SLICER_SLICER_H
+9 -121
Ver Arquivo
@@ -1,16 +1,11 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <stdio.h>
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#include <algorithm> // remove_if
#include "SlicerLayer.h"
#include "../TextureProcessor.h"
#include "../utils/SparsePointGridInclusive.h"
#include "utils/gettime.h"
#include "utils/logoutput.h"
#include "utils/SparsePointGridInclusive.h"
#include "slicer.h"
namespace cura {
namespace cura
{
int largest_neglected_gap_first_phase = MM2INT(0.01); //!< distance between two line segments regarded as connected
int largest_neglected_gap_second_phase = MM2INT(0.02); //!< distance between two line segments regarded as connected
@@ -774,6 +769,8 @@ void SlicerLayer::makePolygons(const Mesh* mesh, bool keep_none_closed, bool ext
auto it = std::remove_if(polygons.begin(), polygons.end(), [snapDistance](PolygonRef poly) { return poly.shorterThan(snapDistance); });
polygons.erase(it, polygons.end());
TextureProcessor::processBumpMap(mesh, *this);
//Finally optimize all the polygons. Every point removed saves time in the long run.
polygons.simplify();
@@ -786,113 +783,4 @@ void SlicerLayer::makePolygons(const Mesh* mesh, bool keep_none_closed, bool ext
}
}
Slicer::Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bool keep_none_closed, bool extensive_stitching)
: mesh(mesh)
{
assert(slice_layer_count > 0);
TimeKeeper slice_timer;
layers.resize(slice_layer_count);
for(int32_t layer_nr = 0; layer_nr < slice_layer_count; layer_nr++)
{
layers[layer_nr].z = initial + thickness * layer_nr;
}
for(unsigned int mesh_idx = 0; mesh_idx < mesh->faces.size(); mesh_idx++)
{
const MeshFace& face = mesh->faces[mesh_idx];
const MeshVertex& v0 = mesh->vertices[face.vertex_index[0]];
const MeshVertex& v1 = mesh->vertices[face.vertex_index[1]];
const MeshVertex& v2 = mesh->vertices[face.vertex_index[2]];
Point3 p0 = v0.p;
Point3 p1 = v1.p;
Point3 p2 = v2.p;
int32_t minZ = p0.z;
int32_t maxZ = p0.z;
if (p1.z < minZ) minZ = p1.z;
if (p2.z < minZ) minZ = p2.z;
if (p1.z > maxZ) maxZ = p1.z;
if (p2.z > maxZ) maxZ = p2.z;
int32_t layer_max = (maxZ - initial) / thickness;
for(int32_t layer_nr = (minZ - initial) / thickness; layer_nr <= layer_max; layer_nr++)
{
int32_t z = layer_nr * thickness + initial;
if (z < minZ) continue;
if (layer_nr < 0) continue;
SlicerSegment s;
s.endVertex = nullptr;
int end_edge_idx = -1;
if (p0.z < z && p1.z >= z && p2.z >= z)
{
s = project2D(p0, p2, p1, z);
end_edge_idx = 0;
if (p1.z == z)
{
s.endVertex = &v1;
}
}
else if (p0.z > z && p1.z < z && p2.z < z)
{
s = project2D(p0, p1, p2, z);
end_edge_idx = 2;
}
else if (p1.z < z && p0.z >= z && p2.z >= z)
{
s = project2D(p1, p0, p2, z);
end_edge_idx = 1;
if (p2.z == z)
{
s.endVertex = &v2;
}
}
else if (p1.z > z && p0.z < z && p2.z < z)
{
s = project2D(p1, p2, p0, z);
end_edge_idx = 0;
}
else if (p2.z < z && p1.z >= z && p0.z >= z)
{
s = project2D(p2, p1, p0, z);
end_edge_idx = 2;
if (p0.z == z)
{
s.endVertex = &v0;
}
}
else if (p2.z > z && p1.z < z && p0.z < z)
{
s = project2D(p2, p0, p1, z);
end_edge_idx = 1;
}
else
{
//Not all cases create a segment, because a point of a face could create just a dot, and two touching faces
// on the slice would create two segments
continue;
}
layers[layer_nr].face_idx_to_segment_idx.insert(std::make_pair(mesh_idx, layers[layer_nr].segments.size()));
s.faceIndex = mesh_idx;
s.endOtherFaceIdx = face.connected_face_index[end_edge_idx];
s.addedToPolygon = false;
layers[layer_nr].segments.push_back(s);
}
}
log("slice of mesh took %.3f seconds\n",slice_timer.restart());
for(unsigned int layer_nr=0; layer_nr<layers.size(); layer_nr++)
{
layers[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
}
mesh->expandXY(mesh->getSettingInMicrons("xy_offset"));
log("slice make polygons took %.3f seconds\n",slice_timer.restart());
}
}//namespace cura
} // namespace cura
+18 -80
Ver Arquivo
@@ -1,47 +1,21 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#ifndef SLICER_H
#define SLICER_H
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef SLICER_SLICER_LAYER_H
#define SLICER_SLICER_LAYER_H
#include <queue>
#include <unordered_map>
#include "mesh.h"
#include "utils/polygon.h"
/*
The Slicer creates layers of polygons from an optimized 3D model.
The result of the Slicer is a list of polygons without any order or structure.
*/
namespace cura {
#include "../mesh.h"
#include "../utils/intpoint.h"
#include "../utils/polygon.h"
class SlicerSegment
#include "SlicerSegment.h"
#include "GapCloserResult.h"
#include "ClosePolygonResult.h"
#include "../MatSegment.h"
namespace cura
{
public:
Point start, end;
int faceIndex = -1;
// The index of the other face connected via the edge that created end
int endOtherFaceIdx = -1;
// If end corresponds to a vertex of the mesh, then this is populated
// with the vertex that it ended on.
const MeshVertex *endVertex = nullptr;
bool addedToPolygon = false;
};
class ClosePolygonResult
{ //The result of trying to find a point on a closed polygon line. This gives back the point index, the polygon index, and the point of the connection.
//The line on which the point lays is between pointIdx-1 and pointIdx
public:
Point intersectionPoint;
int polygonIdx = -1;
unsigned int pointIdx = -1;
};
class GapCloserResult
{
public:
int64_t len = -1;
int polygonIdx = -1;
unsigned int pointIdxA = -1;
unsigned int pointIdxB = -1;
bool AtoB = false;
};
class SlicerLayer
{
@@ -52,6 +26,8 @@ public:
int z = -1;
Polygons polygons;
Polygons openPolylines;
std::unordered_map<SlicerSegment, MatSegment> segment_to_material_segment;
/*!
* Connect the segments into polygons for this layer of this \p mesh
@@ -483,44 +459,6 @@ private:
bool allow_reverse);
};
class Slicer
{
public:
std::vector<SlicerLayer> layers;
} // namespace cura
const Mesh* mesh = nullptr; //!< The sliced mesh
Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bool keepNoneClosed, bool extensiveStitching);
/*!
* Linear interpolation
*
* Get the Y of a point with X \p x in the line through (\p x0, \p y0) and (\p x1, \p y1)
*/
int64_t interpolate(int64_t x, int64_t x0, int64_t x1, int64_t y0, int64_t y1) const
{
int64_t dx_01 = x1 - x0;
int64_t num = (y1 - y0) * (x - x0);
num += num > 0 ? dx_01/2 : -dx_01/2; // add in offset to round result
int64_t y = y0 + num / dx_01;
return y;
}
SlicerSegment project2D(Point3& p0, Point3& p1, Point3& p2, int32_t z) const
{
SlicerSegment seg;
seg.start.X = interpolate(z, p0.z, p1.z, p0.x, p1.x);
seg.start.Y = interpolate(z, p0.z, p1.z, p0.y, p1.y);
seg.end .X = interpolate(z, p0.z, p2.z, p0.x, p2.x);
seg.end .Y = interpolate(z, p0.z, p2.z, p0.y, p2.y);
return seg;
}
void dumpSegmentsToHTML(const char* filename);
};
}//namespace cura
#endif//SLICER_H
#endif // SLICER_SLICER_LAYER_H
+57
Ver Arquivo
@@ -0,0 +1,57 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef SLICER_SLICER_SEGMENT_H
#define SLICER_SLICER_SEGMENT_H
#include <functional>
#include "../utils/intpoint.h"
namespace cura
{
class SlicerSegment
{
public:
Point start, end;
int faceIndex = -1;
// The index of the other face connected via the edge that created end
int endOtherFaceIdx = -1;
// If end corresponds to a vertex of the mesh, then this is populated
// with the vertex that it ended on.
const MeshVertex *endVertex = nullptr;
bool addedToPolygon = false;
SlicerSegment() //!< non-initializing constructor
{}
SlicerSegment(Point start, Point end) //!< partially initializing constructor
: start(start)
, end(end)
{}
/*!
* equivalence testing irrespective of start/end order
*/
bool operator==(const SlicerSegment& b) const
{
return (start == b.start && end == b.end) || (start == b.end && end == b.start);
}
};
} // namespace cura
namespace std
{
/*!
* hash function irrespective of start/end order
*/
template<> struct hash<cura::SlicerSegment>
{
typedef std::size_t result_type;
result_type operator()(cura::SlicerSegment const& s) const
{
return std::hash<cura::Point>()(cura::operator+(s.start, s.end));
}
};
} // namespace std
#endif // SLICER_SLICER_SEGMENT_H
+74
Ver Arquivo
@@ -0,0 +1,74 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef UTILS_F_POINT_H
#define UTILS_F_POINT_H
#include <cmath> // sqrt
#include <iostream> // auto-serialization / auto-toString() '<<'
namespace cura
{
/*!
* 2D coordinates represented by floats
*/
class FPoint
{
public:
float x, y; //!< Coordinates
FPoint() //!< non-initializing constructor
{}
FPoint(float x, float y) //!< constructor
: x(x)
, y(y)
{}
FPoint operator+(const FPoint& p) const { return FPoint(x+p.x, y+p.y); }
FPoint operator-(const FPoint& p) const { return FPoint(x-p.x, y-p.y); }
FPoint operator/(const float i) const { return FPoint(x/i, y/i); }
FPoint operator*(const float i) const { return FPoint(x*i, y*i); }
FPoint& operator += (const FPoint& p) { x += p.x; y += p.y; return *this; }
FPoint& operator -= (const FPoint& p) { x -= p.x; y -= p.y; return *this; }
bool operator==(const FPoint& p) const { return x == p.x && y == p.y; }
bool operator!=(const FPoint& p) const { return x != p.x || y != p.y; }
/*!
* output to string stream in standard format
*/
template<class CharT, class TraitsT>
friend
std::basic_ostream<CharT, TraitsT>&
operator <<(std::basic_ostream<CharT, TraitsT>& os, const FPoint& p)
{
return os << "(" << p.x << ", " << p.y << ")";
}
/*!
* squared vector size
*/
float vSize2() const
{
return x * x + y * y;
}
/*!
* vector size
*/
float vSize() const
{
return sqrt(vSize2());
}
/*!
* dot product
*/
float dot(const FPoint& p) const
{
return x * p.x + y * p.y;
}
};
} // namespace cura
#endif // UTILS_F_POINT_H
+10
Ver Arquivo
@@ -190,6 +190,16 @@ unsigned int Polygons::findInside(Point p, bool border_result)
return ret;
}
Polygons Polygons::removeComplexParts() const
{
Polygons ret;
ClipperLib::Clipper clipper(clipper_init);
clipper.AddPaths(paths, ClipperLib::ptSubject, true);
clipper.Execute(ClipperLib::ctUnion, ret.paths, ClipperLib::pftPositive);
return ret;
}
Polygons Polygons::offset(int distance, ClipperLib::JoinType join_type, double miter_limit) const
{
Polygons ret;
+12
Ver Arquivo
@@ -859,6 +859,18 @@ public:
return ret;
}
/*!
* Remove holes which are lying outside of parts, and outlines inside of parts
*
* ^
* ^
* <<<<<<<<^<<<< should become <<<<<<<<
* ^ ^
* ^ ^
* ^ ^
*/
Polygons removeComplexParts() const;
int64_t polygonLength() const
{
int64_t length = 0;