Welcome to mirror list, hosted at ThFree Co, Russian Federation.

SlicingAdaptive.cpp « libslic3r « src « xs - github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ff0da76365c6ebef8c9bc055a115af29c18417a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "libslic3r.h"
#include "TriangleMesh.hpp"
#include "SlicingAdaptive.hpp"

namespace Slic3r
{

void SlicingAdaptive::clear()
{
	m_meshes.clear();
	m_faces.clear();
	m_face_normal_z.clear();
}

std::pair<float, float> face_z_span(const stl_facet *f)
{
	return std::pair<float, float>(
		std::min(std::min(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z),
		std::max(std::max(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z));
}

void SlicingAdaptive::prepare()
{
	// 1) Collect faces of all meshes.
	int nfaces_total = 0;
	for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh)
		nfaces_total += (*it_mesh)->stl.stats.number_of_facets;
	m_faces.reserve(nfaces_total);
	for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh)
		for (int i = 0; i < (*it_mesh)->stl.stats.number_of_facets; ++ i)
			m_faces.push_back((*it_mesh)->stl.facet_start + i);

	// 2) Sort faces lexicographically by their Z span.
	std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) {
		std::pair<float, float> span1 = face_z_span(f1);
		std::pair<float, float> span2 = face_z_span(f2);
		return span1 < span2;
	});

	// 3) Generate Z components of the facet normals.
	m_face_normal_z.assign(m_faces.size(), 0.f);
    for (size_t iface = 0; iface < m_faces.size(); ++ iface)
    	m_face_normal_z[iface] = m_faces[iface]->normal.z;
}

float SlicingAdaptive::cusp_height(float z, float cusp_value, int &current_facet)
{
	float height = m_slicing_params.max_layer_height;
	bool first_hit = false;
	
	// find all facets intersecting the slice-layer
	int ordered_id = current_facet;
	for (; ordered_id < int(m_faces.size()); ++ ordered_id) {
		std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]);
		// facet's minimum is higher than slice_z -> end loop
		if (zspan.first >= z)
			break;
		// facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point
		if (zspan.second > z) {
			// first event?
			if (! first_hit) {
				first_hit = true;
				current_facet = ordered_id;
			}
			// skip touching facets which could otherwise cause small cusp values
			if (zspan.second <= z + EPSILON)
				continue;
			// compute cusp-height for this facet and store minimum of all heights
			float normal_z = m_face_normal_z[ordered_id];
			height = std::min(height, (normal_z == 0.f) ? 9999.f : std::abs(cusp_value / normal_z));
		}
	}

	// lower height limit due to printer capabilities
	height = std::max(height, float(m_slicing_params.min_layer_height));

	// check for sloped facets inside the determined layer and correct height if necessary
	if (height > m_slicing_params.min_layer_height) {
		for (; ordered_id < int(m_faces.size()); ++ ordered_id) {
			std::pair<float, float> zspan = face_z_span(m_faces[ordered_id]);
			// facet's minimum is higher than slice_z + height -> end loop
			if (zspan.first >= z + height)
				break;

			// skip touching facets which could otherwise cause small cusp values
			if (zspan.second <= z + EPSILON)
				continue;

			// Compute cusp-height for this facet and check against height.
			float normal_z = m_face_normal_z[ordered_id];
			float cusp = (normal_z == 0) ? 9999 : abs(cusp_value / normal_z);
			
			float z_diff = zspan.first - z;

			// handle horizontal facets
			if (m_face_normal_z[ordered_id] > 0.999) {
				// Slic3r::debugf "cusp computation, height is reduced from %f", $height;
				height = z_diff;
				// Slic3r::debugf "to %f due to near horizontal facet\n", $height;
			} else if (cusp > z_diff) {
				if (cusp < height) {
					// Slic3r::debugf "cusp computation, height is reduced from %f", $height;
					height = cusp;
					// Slic3r::debugf "to %f due to new cusp height\n", $height;
				}
			} else {
				// Slic3r::debugf "cusp computation, height is reduced from %f", $height;
				height = z_diff;
				// Slic3r::debugf "to z-diff: %f\n", $height;
			}
		}
		// lower height limit due to printer capabilities again
		height = std::max(height, float(m_slicing_params.min_layer_height));
	}
	
//	Slic3r::debugf "cusp computation, layer-bottom at z:%f, cusp_value:%f, resulting layer height:%f\n", unscale $z, $cusp_value, $height;	
	return height; 
}

// Returns the distance to the next horizontal facet in Z-dir 
// to consider horizontal object features in slice thickness
float SlicingAdaptive::horizontal_facet_distance(float z)
{
	for (size_t i = 0; i < m_faces.size(); ++ i) {
		std::pair<float, float> zspan = face_z_span(m_faces[i]);
		// facet's minimum is higher than max forward distance -> end loop
		if (zspan.first > z + m_slicing_params.max_layer_height)
			break;
		// min_z == max_z -> horizontal facet
		if (zspan.first > z && zspan.first == zspan.second)
			return zspan.first - z;
	}
	
	// objects maximum?
	return (z + m_slicing_params.max_layer_height > m_slicing_params.object_print_z_height()) ? 
		std::max<float>(m_slicing_params.object_print_z_height() - z, 0.f) :
		m_slicing_params.max_layer_height;
}

}; // namespace Slic3r