TPMS-D Infill ( Triply Periodic Minimal Surface D) (#9613)

* Fill TPMS-D

limpieza

* delete unused function

* cleaning

* Icon update

* fix missing header

* density Adjusted

Co-Authored-By: Ian Bassi <12130714+ianalexis@users.noreply.github.com>

* Improve Precision +  refactoring

clean tpms.hpp

Co-Authored-By: Ian Bassi <12130714+ianalexis@users.noreply.github.com>

---------

Co-authored-by: Ian Bassi <12130714+ianalexis@users.noreply.github.com>
Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
This commit is contained in:
Rodrigo 2025-06-15 08:38:54 -03:00 committed by GitHub
parent e13ec786d5
commit 1471276580
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 681 additions and 2 deletions

View file

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
version="1.1"
id="svg10"
sodipodi:docname="param_tpmsd.svg"
inkscape:version="1.4.2 (ebf0e94, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs10" />
<sodipodi:namedview
id="namedview10"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="24.479167"
inkscape:cx="12.214468"
inkscape:cy="12.88851"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg10"
showguides="true">
<sodipodi:guide
position="7.4348935,20.691064"
orientation="1,0"
id="guide13"
inkscape:locked="false" />
<sodipodi:guide
position="10.662128,17.545532"
orientation="0,-1"
id="guide14"
inkscape:locked="false" />
<sodipodi:guide
position="17.525106,21.140426"
orientation="1,0"
id="guide19"
inkscape:locked="false" />
<sodipodi:guide
position="11.029787,7.4961704"
orientation="0,-1"
id="guide20"
inkscape:locked="false" />
</sodipodi:namedview>
<line
x1="1.5"
y1="17.5"
x2="17.5"
y2="1.5"
style="fill:none;stroke:#949494;stroke-linecap:round;stroke-linejoin:round;opacity:0.75"
id="line1" />
<line
x1="22.5"
y1="16.5"
x2="17.5"
y2="21.5"
style="fill:none;stroke:#949494;stroke-linecap:round;stroke-linejoin:round;opacity:0.75"
id="line2" />
<line
x1="7.5"
y1="1.5"
x2="1.5"
y2="7.5"
style="fill:none;stroke:#575757;stroke-linecap:round;stroke-linejoin:round;opacity:0.75;stroke-opacity:1"
id="line3" />
<line
x1="22.5"
y1="6.5"
x2="6.5"
y2="22.5"
style="fill:none;stroke:#949494;stroke-linecap:round;stroke-linejoin:round;opacity:0.75"
id="line4" />
<line
x1="18.5"
y1="22.5"
x2="1.5"
y2="5.5"
style="fill:none;stroke:#009688;stroke-linecap:round;stroke-linejoin:round"
id="line7" />
<line
x1="17.5"
y1="1.5"
x2="22.5"
y2="6.5"
style="fill:none;stroke:#009688;stroke-linecap:round;stroke-linejoin:round"
id="line8" />
<line
x1="1.5"
y1="15.5"
x2="8.5"
y2="22.5"
style="fill:none;stroke:#009688;stroke-linecap:round;stroke-linejoin:round"
id="line9" />
<line
x1="7.5"
y1="1.5"
x2="22.5"
y2="16.5"
style="fill:none;stroke:#009688;stroke-linecap:round;stroke-linejoin:round"
id="line10" />
<path
d="M3.5,1.5h17a2,2,0,0,1,2,2v17a2,2,0,0,1-2,2H3.5a2,2,0,0,1-2-2V3.5A2,2,0,0,1,3.5,1.5Z"
style="fill:none;stroke:#949494;stroke-linecap:round;stroke-linejoin:round"
id="path10" />
<path
style="fill:#939393;fill-opacity:1;stroke:none;stroke-width:0.0408511"
d="M 2.90923,22.896259 C 2.0613133,22.674106 1.4709446,22.121791 1.1317723,21.233374 l -0.09007,-0.235927 -0.010758,-8.854467 c -0.0094,-7.7388928 -0.00304,-8.8917826 0.050495,-9.1506389 0.1859554,-0.8991302 0.9034473,-1.644147 1.8305395,-1.9007639 0.2366323,-0.065499 0.8566253,-0.070301 9.0778082,-0.070301 7.25241,0 8.863843,0.00978 9.048511,0.054939 0.41936,0.1025422 0.894759,0.3676462 1.184681,0.6606312 0.460787,0.465656 0.674736,0.9256377 0.740656,1.5923869 0.02306,0.2331921 0.03324,3.8138627 0.02551,8.9669367 -0.01218,8.11996 -0.0168,8.591678 -0.08634,8.820989 -0.280161,0.923863 -1.004037,1.61516 -1.884942,1.800108 -0.246575,0.05177 -1.492743,0.05983 -9.04851,0.0585 -8.488697,-0.0015 -8.7718539,-0.004 -9.0601322,-0.07951 z m 18.140693,-0.972914 c 0.331179,-0.133671 0.679356,-0.465886 0.829868,-0.791824 l 0.118507,-0.256627 0.01067,-8.781151 C 22.020819,2.3471958 22.04116,3.0891606 21.749942,2.6450177 21.599404,2.4154289 21.375482,2.2298349 21.079149,2.0890425 l -0.18383,-0.08734 H 12.010213 3.1251064 L 2.8684789,2.1202084 C 2.5425414,2.270721 2.2103264,2.6188978 2.0766551,2.9500767 l -0.095379,0.2363063 -0.011773,8.578723 c -0.00774,5.63809 0.00244,8.687076 0.029697,8.89482 0.093595,0.713409 0.5893405,1.239468 1.2564016,1.333226 0.1304402,0.01833 4.1343554,0.03159 8.8975893,0.02945 l 8.660426,-0.0039 z"
id="path18" />
<path
style="fill:#575757;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511;stroke-opacity:1"
d="m 12.847206,16.115289 -0.325345,-0.327265 2.133833,-2.133833 2.133833,-2.133833 0.336923,0.336924 0.336923,0.336923 -2.12388,2.124174 c -1.168133,1.168296 -2.133568,2.124174 -2.14541,2.124174 -0.01184,0 -0.167937,-0.147269 -0.346877,-0.327264 z"
id="path21" />
<path
style="fill:#575757;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511;stroke-opacity:1"
d="m 7.8534456,21.130094 -0.3361443,-0.3379 2.1346396,-2.134349 2.1346401,-2.134349 0.336144,0.3379 0.336144,0.337899 -2.13464,2.134349 -2.1346391,2.134349 z"
id="path22" />
<path
style="fill:#575757;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511;stroke-opacity:1"
d="m 6.546827,21.763848 0.2344496,-0.234449 0.2344496,0.234449 0.2344496,0.23445 H 6.7812766 6.3123774 Z"
id="path23" />
<path
style="fill:#575757;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511;stroke-opacity:1"
d="m 17.861947,11.121574 -0.336135,-0.33789 2.13578,-2.1354894 2.135779,-2.135489 0.09025,0.096067 c 0.0827,0.088027 0.09025,0.1368911 0.09025,0.583812 v 0.4877446 l -1.889895,1.8895673 -1.889895,1.8895675 z"
id="path24" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="m 6.5877715,21.763941 0.193505,-0.193505 0.193505,0.193505 0.1935051,0.193506 H 6.7812765 6.3942664 Z"
id="path1" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="M 7.8529991,21.088808 7.558256,20.792085 9.6516156,18.699021 c 1.1513474,-1.151185 2.1121364,-2.093064 2.1350854,-2.093064 0.02295,0 0.174361,0.133526 0.33647,0.296724 l 0.294743,0.296723 -2.09336,2.093064 c -1.1513475,1.151185 -2.1121362,2.093064 -2.1350855,2.093064 -0.022949,0 -0.1743606,-0.133526 -0.3364694,-0.296724 z"
id="path2" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="m 12.847659,16.074118 -0.285957,-0.284076 2.113902,-2.114406 2.113903,-2.114406 0.316736,0.318165 0.316735,0.318166 -2.093037,2.081645 c -1.15117,1.144905 -2.116277,2.081047 -2.144681,2.080316 -0.0284,-7.31e-4 -0.180324,-0.129163 -0.337601,-0.285404 z"
id="path3" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="m 17.86151,11.080298 -0.294742,-0.296722 2.118341,-2.118048 c 2.117619,-2.1173249 2.118364,-2.1180149 2.185127,-2.0226982 0.05244,0.074868 0.06679,0.1965381 0.06679,0.5664281 v 0.4710787 l -1.848677,1.8483423 c -1.016773,1.0165881 -1.867445,1.8483421 -1.890384,1.8483421 -0.02294,0 -0.174341,-0.133525 -0.33645,-0.296723 z"
id="path4" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="M 2.8696064,6.137744 2.5334527,5.7998348 4.422634,3.9109812 6.3118152,2.0221276 H 6.804957 c 0.4607028,0 0.4989051,0.00614 0.5807596,0.093265 L 7.4733352,2.2086584 5.3395475,4.3421556 3.20576,6.475653 Z"
id="path5" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="m 17.861947,21.130084 -0.336135,-0.33789 2.135779,-2.135489 2.13578,-2.135489 0.09025,0.09607 c 0.0827,0.08803 0.09025,0.136891 0.09025,0.583812 v 0.487745 l -1.889895,1.889567 -1.889895,1.889567 z"
id="path6" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="M 7.8633763,11.131459 7.5380311,10.804194 9.6718639,8.6703613 11.805697,6.5365285 12.14262,6.8734517 12.479543,7.2103748 10.355663,9.334549 c -1.1681333,1.168296 -2.1335682,2.124174 -2.1454103,2.124174 -0.011842,0 -0.1679366,-0.147269 -0.3468764,-0.327264 z"
id="path7" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="m 2.8696157,16.146264 -0.3361442,-0.3379 2.1346395,-2.134349 2.1346397,-2.134349 0.3361442,0.3379 0.3361442,0.337899 -2.1346396,2.134349 -2.1346395,2.134349 z"
id="path8" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="m 2.0017021,17.218723 v -0.468899 l 0.2344496,0.23445 0.2344496,0.234449 -0.2344496,0.23445 -0.2344496,0.234449 z"
id="path9" />
<path
style="fill:#949494;fill-opacity:0.74902;stroke:#575757;stroke-width:0.0408511"
d="M 12.878117,6.137744 12.541963,5.7998348 14.431144,3.9109812 16.320326,2.0221276 h 0.493142 c 0.460702,0 0.498905,0.00614 0.580759,0.093265 l 0.08762,0.093265 -2.133788,2.1334972 -2.133787,2.1334974 z"
id="path11" />
<path
style="fill:#009688;fill-opacity:1;stroke:#575757;stroke-width:0.0408511"
d="M 6.8044173,8.9013728 C 5.8891463,8.6799894 5.1293329,7.9312103 4.8777561,7.0026907 4.7837651,6.6557878 4.7837651,6.0488929 4.8777561,5.70199 5.3133212,4.0944072 7.0721201,3.2823661 8.5576782,4.0029623 9.8573624,4.6333971 10.401452,6.2283001 9.7552143,7.513329 9.4074091,8.204932 8.7490599,8.7280789 8.0061889,8.9031641 7.6791867,8.9802341 7.1270552,8.9794111 6.8044173,8.9013741 Z M 7.7254879,7.9858114 c 0.518457,-0.097597 0.962572,-0.4436182 1.1925798,-0.929168 0.1209241,-0.2552726 0.1304428,-0.3066675 0.1304428,-0.704303 0,-0.3976356 -0.00952,-0.4490305 -0.1304428,-0.7043031 -0.6030824,-1.2731159 -2.4041171,-1.2731159 -3.0071994,0 -0.1209241,0.2552726 -0.1304429,0.3066675 -0.1304429,0.7043031 0,0.3976355 0.00952,0.4490304 0.1304429,0.704303 0.3306819,0.6980745 1.0595769,1.0713019 1.8146196,0.929168 z"
id="path19" />
<path
style="fill:#009688;fill-opacity:1;stroke:#575757;stroke-width:0.0408511"
d="M 16.935481,8.9013728 C 16.02021,8.6799894 15.260397,7.9312103 15.00882,7.0026907 c -0.09399,-0.3469029 -0.09399,-0.9537978 0,-1.3007007 0.435565,-1.6075828 2.194364,-2.4196239 3.679922,-1.6990277 1.299684,0.6304348 1.843774,2.2253378 1.197536,3.5103667 -0.347805,0.691603 -1.006154,1.2147499 -1.749025,1.3898351 -0.327003,0.07707 -0.879134,0.076247 -1.201772,-0.00179 z m 0.921071,-0.9155614 c 0.518457,-0.097597 0.962572,-0.4436182 1.192579,-0.929168 0.120924,-0.2552726 0.130443,-0.3066675 0.130443,-0.704303 0,-0.3976356 -0.0095,-0.4490305 -0.130443,-0.7043031 -0.603082,-1.2731159 -2.404117,-1.2731159 -3.007199,0 -0.120924,0.2552726 -0.130443,0.3066675 -0.130443,0.7043031 0,0.3976355 0.0095,0.4490304 0.130443,0.704303 0.330682,0.6980745 1.059577,1.0713019 1.81462,0.929168 z"
id="path20" />
<path
style="fill:#009688;fill-opacity:1;stroke:#575757;stroke-width:0.0408511"
d="m 6.8044173,19.073288 c -0.915271,-0.221384 -1.6750844,-0.970163 -1.9266612,-1.898683 -0.093991,-0.346902 -0.093991,-0.953797 0,-1.3007 0.4355651,-1.607583 2.194364,-2.419624 3.6799221,-1.699028 1.2996842,0.630435 1.8437738,2.225338 1.1975361,3.510367 -0.3478052,0.691603 -1.0061544,1.21475 -1.7490254,1.389835 -0.3270022,0.07707 -0.8791337,0.07625 -1.2017716,-0.0018 z m 0.9210706,-0.915562 c 0.518457,-0.0976 0.962572,-0.443618 1.1925798,-0.929168 0.1209241,-0.255272 0.1304428,-0.306667 0.1304428,-0.704303 0,-0.397635 -0.00952,-0.44903 -0.1304428,-0.704303 -0.6030824,-1.273116 -2.4041171,-1.273116 -3.0071994,0 -0.1209241,0.255273 -0.1304429,0.306668 -0.1304429,0.704303 0,0.397636 0.00952,0.449031 0.1304429,0.704303 0.3306819,0.698075 1.0595769,1.071302 1.8146196,0.929168 z"
id="path25" />
<path
style="fill:#009688;fill-opacity:1;stroke:#575757;stroke-width:0.0408511"
d="m 16.935481,19.073288 c -0.915271,-0.221384 -1.675084,-0.970163 -1.926661,-1.898683 -0.09399,-0.346902 -0.09399,-0.953797 0,-1.3007 0.435565,-1.607583 2.194364,-2.419624 3.679922,-1.699028 1.299684,0.630435 1.843774,2.225338 1.197536,3.510367 -0.347805,0.691603 -1.006154,1.21475 -1.749025,1.389835 -0.327003,0.07707 -0.879134,0.07625 -1.201772,-0.0018 z m 0.921071,-0.915562 c 0.518457,-0.0976 0.962572,-0.443618 1.192579,-0.929168 0.120924,-0.255272 0.130443,-0.306667 0.130443,-0.704303 0,-0.397635 -0.0095,-0.44903 -0.130443,-0.704303 -0.603082,-1.273116 -2.404117,-1.273116 -3.007199,0 -0.120924,0.255273 -0.130443,0.306668 -0.130443,0.704303 0,0.397636 0.0095,0.449031 0.130443,0.704303 0.330682,0.698075 1.059577,1.071302 1.81462,0.929168 z"
id="path26" />
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -101,6 +101,8 @@ set(lisbslic3r_sources
Fill/FillHoneycomb.hpp
Fill/FillGyroid.cpp
Fill/FillGyroid.hpp
Fill/FillTpmsD.cpp
Fill/FillTpmsD.hpp
Fill/FillPlanePath.cpp
Fill/FillPlanePath.hpp
Fill/FillLine.cpp

View file

@ -14,6 +14,7 @@
#include "FillRectilinear.hpp"
#include "FillLightning.hpp"
#include "FillConcentricInternal.hpp"
#include "FillTpmsD.hpp"
#include "FillConcentric.hpp"
#include "libslic3r.h"
@ -1047,6 +1048,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
case ipHoneycomb:
case ip3DHoneycomb:
case ipGyroid:
case ipTpmsD:
case ipHilbertCurve:
case ipArchimedeanChords:
case ipOctagramSpiral: break;

View file

@ -16,6 +16,7 @@
#include "FillHoneycomb.hpp"
#include "Fill3DHoneycomb.hpp"
#include "FillGyroid.hpp"
#include "FillTpmsD.hpp"
#include "FillPlanePath.hpp"
#include "FillLine.hpp"
#include "FillRectilinear.hpp"
@ -41,6 +42,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipHoneycomb: return new FillHoneycomb();
case ip3DHoneycomb: return new Fill3DHoneycomb();
case ipGyroid: return new FillGyroid();
case ipTpmsD: return new FillTpmsD();//from creality print
case ipRectilinear: return new FillRectilinear();
case ipAlignedRectilinear: return new FillAlignedRectilinear();
case ipCrossHatch: return new FillCrossHatch();

View file

@ -0,0 +1,446 @@
#include "../ClipperUtils.hpp"
#include "FillTpmsD.hpp"
#include <cmath>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <tbb/parallel_for.h>
// From Creality Print
namespace Slic3r {
using namespace std;
struct myPoint
{
coord_t x, y;
};
class LineSegmentMerger
{
public:
void mergeSegments(const vector<pair<myPoint, myPoint>>& segments, vector<vector<myPoint>>& polylines2)
{
std::unordered_map<int, myPoint> point_id_xy;
std::set<std::pair<int, int>> segment_ids;
std::unordered_map<int64_t, int> map_keyxy_pointid;
auto get_itr = [&](coord_t x, coord_t y) {
for (auto i : {0}) //,-2,2
{
for (auto j : {0}) //,-2,2
{
int64_t combined_key1 = static_cast<int64_t>(x + i) << 32 | static_cast<uint32_t>(y + j);
auto itr1 = map_keyxy_pointid.find(combined_key1);
if (itr1 != map_keyxy_pointid.end()) {
return itr1;
}
}
}
return map_keyxy_pointid.end();
};
int pointid = 0;
for (const auto& segment : segments) {
coord_t x = segment.first.x;
coord_t y = segment.first.y;
auto itr = get_itr(x, y);
int segmentid0 = -1;
if (itr == map_keyxy_pointid.end()) {
int64_t combined_key = static_cast<int64_t>(x) << 32 | static_cast<uint32_t>(y);
segmentid0 = pointid;
point_id_xy[pointid] = segment.first;
map_keyxy_pointid[combined_key] = pointid++;
} else {
segmentid0 = itr->second;
}
int segmentid1 = -1;
x = segment.second.x;
y = segment.second.y;
itr = get_itr(x, y);
if (itr == map_keyxy_pointid.end()) {
int64_t combined_key = static_cast<int64_t>(x) << 32 | static_cast<uint32_t>(y);
segmentid1 = pointid;
point_id_xy[pointid] = segment.second;
map_keyxy_pointid[combined_key] = pointid++;
} else {
segmentid1 = itr->second;
}
if (segmentid0 != segmentid1) {
segment_ids.insert(segmentid0 < segmentid1 ? std::make_pair(segmentid0, segmentid1) :
std::make_pair(segmentid1, segmentid0));
}
}
unordered_map<int, vector<int>> graph;
unordered_set<int> visited;
vector<vector<int>> polylines;
// Build the graph
for (const auto& segment : segment_ids) {
graph[segment.first].push_back(segment.second);
graph[segment.second].push_back(segment.first);
}
vector<int> startnodes;
for (const auto& node : graph) {
if (node.second.size() == 1) {
startnodes.push_back(node.first);
}
}
// Find all connected components
for (const auto& point_first : startnodes) {
if (visited.find(point_first) == visited.end()) {
vector<int> polyline;
dfs(point_first, graph, visited, polyline);
polylines.push_back(std::move(polyline));
}
}
for (const auto& point : graph) {
if (visited.find(point.first) == visited.end()) {
vector<int> polyline;
dfs(point.first, graph, visited, polyline);
polylines.push_back(std::move(polyline));
}
}
for (auto& pl : polylines) {
vector<myPoint> tmpps;
for (auto& pid : pl) {
tmpps.push_back(point_id_xy[pid]);
}
polylines2.push_back(tmpps);
}
}
private:
void dfs(const int& start_node,
std::unordered_map<int, std::vector<int>>& graph,
std::unordered_set<int>& visited,
std::vector<int>& polyline)
{
std::vector<int> stack;
stack.reserve(graph.size());
stack.push_back(start_node);
while (!stack.empty()) {
int node = stack.back();
stack.pop_back();
if (!visited.insert(node).second) {
continue;
}
polyline.push_back(node);
auto& neighbors = graph[node];
for (const auto& neighbor : neighbors) {
if (visited.find(neighbor) == visited.end()) {
stack.push_back(neighbor);
}
}
}
}
};
namespace MarchingSquares {
struct Point
{
double x, y;
};
vector<double> getGridValues(int i, int j, vector<vector<double>>& data)
{
vector<double> values;
values.push_back(data[i][j + 1]);
values.push_back(data[i + 1][j + 1]);
values.push_back(data[i + 1][j]);
values.push_back(data[i][j]);
return values;
}
bool needContour(double value, double contourValue) { return value >= contourValue; }
Point interpolate(std::vector<std::vector<MarchingSquares::Point>>& posxy,
std::vector<int> p1ij,
std::vector<int> p2ij,
double v1,
double v2,
double contourValue)
{
Point p1;
p1.x = posxy[p1ij[0]][p1ij[1]].x;
p1.y = posxy[p1ij[0]][p1ij[1]].y;
Point p2;
p2.x = posxy[p2ij[0]][p2ij[1]].x;
p2.y = posxy[p2ij[0]][p2ij[1]].y;
double mu = (contourValue - v1) / (v2 - v1);
Point p;
p.x = p1.x + mu * (p2.x - p1.x);
p.y = p1.y + mu * (p2.y - p1.y);
return p;
}
void process_block(int i,
int j,
vector<vector<double>>& data,
double contourValue,
std::vector<std::vector<MarchingSquares::Point>>& posxy,
vector<Point>& contourPoints)
{
vector<double> values = getGridValues(i, j, data);
vector<bool> isNeedContour;
for (double value : values) {
isNeedContour.push_back(needContour(value, contourValue));
}
int index = 0;
if (isNeedContour[0])
index |= 1;
if (isNeedContour[1])
index |= 2;
if (isNeedContour[2])
index |= 4;
if (isNeedContour[3])
index |= 8;
vector<Point> points;
switch (index) {
case 0:
case 15: break;
case 1:
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
break;
case 14:
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
break;
case 2:
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
break;
case 13:
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
break;
case 3:
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
break;
case 12:
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
break;
case 4:
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
break;
case 11:
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
break;
case 5:
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
points.push_back(interpolate(posxy, {i, j}, {i + 1, j}, values[3], values[2], contourValue));
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
break;
case 6:
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
break;
case 9:
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
break;
case 7:
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
break;
case 8:
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
points.push_back(interpolate(posxy, {i + 1, j}, {i, j}, values[2], values[3], contourValue));
break;
case 10:
points.push_back(interpolate(posxy, {i, j}, {i, j + 1}, values[3], values[0], contourValue));
points.push_back(interpolate(posxy, {i, j}, {i + 1, j}, values[3], values[2], contourValue));
points.push_back(interpolate(posxy, {i, j + 1}, {i + 1, j + 1}, values[0], values[1], contourValue));
points.push_back(interpolate(posxy, {i + 1, j + 1}, {i + 1, j}, values[1], values[2], contourValue));
break;
}
for (Point& p : points) {
contourPoints.push_back(p);
}
}
void drawContour(double contourValue,
int gridSize_w,
int gridSize_h,
vector<vector<double>>& data,
std::vector<std::vector<MarchingSquares::Point>>& posxy,
Polylines& repls)
{
vector<Point> contourPoints;
int total_size = (gridSize_h - 1) * (gridSize_w - 1);
vector<vector<Point>> contourPointss;
contourPointss.resize(total_size);
tbb::parallel_for(tbb::blocked_range<size_t>(0, total_size),
[&contourValue, &posxy, &contourPointss, &data, &gridSize_w](const tbb::blocked_range<size_t>& range) {
for (size_t k = range.begin(); k < range.end(); ++k) {
int i = k / (gridSize_w - 1); //
int j = k % (gridSize_w - 1); //
process_block(i, j, data, contourValue, posxy, contourPointss[k]);
}
});
vector<pair<myPoint, myPoint>> segments2;
myPoint p1, p2;
for (int k = 0; k < total_size; k++) {
for (int i = 0; i < contourPointss[k].size() / 2; i++) {
p1.x = scale_(contourPointss[k][i * 2].x);
p1.y = scale_(contourPointss[k][i * 2].y);
p2.x = scale_(contourPointss[k][i * 2 + 1].x);
p2.y = scale_(contourPointss[k][i * 2 + 1].y);
segments2.push_back({p1, p2});
}
}
LineSegmentMerger merger;
vector<vector<myPoint>> result;
merger.mergeSegments(segments2, result);
for (vector<myPoint>& p : result) {
Polyline repltmp;
for (myPoint& pt : p) {
repltmp.points.push_back(Slic3r::Point(pt.x, pt.y));
}
repltmp.simplify(scale_(0.05f));
repls.push_back(repltmp);
}
}
} // namespace MarchingSquares
static float sin_table[360];
static float cos_table[360];
static bool g_is_init = false;
#define PIratio 57.29577951308232 // 180/PI
static void initialize_lookup_tables()
{
for (int i = 0; i < 360; ++i) {
float angle = i * (M_PI / 180.0);
sin_table[i] = std::sin(angle);
cos_table[i] = std::cos(angle);
}
}
static float get_sin(float angle)
{
angle = angle * PIratio;
int index = static_cast<int>(std::fmod(angle, 360) + 360) % 360;
return sin_table[index];
}
static float get_cos(float angle)
{
angle = angle * PIratio;
int index = static_cast<int>(std::fmod(angle, 360) + 360) % 360;
return cos_table[index];
}
FillTpmsD::FillTpmsD()
{
if (!g_is_init) {
initialize_lookup_tables();
g_is_init = true;
}
}
void FillTpmsD::_fill_surface_single(const FillParams& params,
unsigned int thickness_layers,
const std::pair<float, Point>& direction,
ExPolygon expolygon,
Polylines& polylines_out)
{
auto infill_angle = float(this->angle - (CorrectionAngle * 2 * M_PI) / 360.);
if (std::abs(infill_angle) >= EPSILON)
expolygon.rotate(-infill_angle);
float vari_T = 2.98 * spacing / params.density; // Infill density adjustment factor for TPMS-D
BoundingBox bb = expolygon.contour.bounding_box();
auto cenpos = unscale(bb.center());
auto boxsize = unscale(bb.size());
float xlen = boxsize.x();
float ylen = boxsize.y();
float delta = 0.25f;
float myperiod = 2 * PI / vari_T;
float c_z = myperiod * this->z;
float cos_z = get_cos(c_z);
float sin_z = get_sin(c_z);
auto scalar_field = [&](float x, float y) {
// TPMS-D
float a_x = myperiod * x;
float b_y = myperiod * y;
float r = get_cos(a_x) * get_cos(b_y) * cos_z - get_sin(a_x) * get_sin(b_y) * sin_z;
return r;
};
std::vector<std::vector<MarchingSquares::Point>> posxy;
int i = 0, j = 0;
std::vector<MarchingSquares::Point> allptpos;
for (float y = -(ylen) / 2.0f - 2; y < (ylen) / 2.0f + 2; y = y + delta, i++) {
j = 0;
std::vector<MarchingSquares::Point> colposxy;
for (float x = -(xlen) / 2.0f - 2; x < (xlen) / 2.0f + 2; x = x + delta, j++) {
MarchingSquares::Point pt;
pt.x = cenpos.x() + x;
pt.y = cenpos.y() + y;
colposxy.push_back(pt);
}
posxy.push_back(colposxy);
}
std::vector<std::vector<double>> data(posxy.size(), std::vector<double>(posxy[0].size()));
int width = posxy[0].size();
int height = posxy.size();
int total_size = (height) * (width);
tbb::parallel_for(tbb::blocked_range<size_t>(0, total_size),
[&width, &scalar_field, &data, &posxy](const tbb::blocked_range<size_t>& range) {
for (size_t k = range.begin(); k < range.end(); ++k) {
int i = k / (width);
int j = k % (width);
data[i][j] = scalar_field(posxy[i][j].x, posxy[i][j].y);
}
});
Polylines polylines;
MarchingSquares::drawContour(0, j, i, data, posxy, polylines);
polylines = intersection_pl(polylines, expolygon);
if (!polylines.empty()) {
// connect lines
size_t polylines_out_first_idx = polylines_out.size();
if (params.dont_connect())
append(polylines_out, chain_polylines(polylines));
else
this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
// new paths must be rotated back
if (std::abs(infill_angle) >= EPSILON) {
for (auto it = polylines_out.begin() + polylines_out_first_idx; it != polylines_out.end(); ++it)
it->rotate(infill_angle);
}
}
}
} // namespace Slic3r

View file

@ -0,0 +1,31 @@
#ifndef slic3r_FillTpmsD_hpp_
#define slic3r_FillTpmsD_hpp_
#include "../libslic3r.h"
#include "FillBase.hpp"
namespace Slic3r {
class FillTpmsD : public Fill
{
public:
FillTpmsD();
Fill* clone() const override { return new FillTpmsD(*this); }
// require bridge flow since most of this pattern hangs in air
bool use_bridge_flow() const override { return false; }
// Correction applied to regular infill angle to maximize printing
// speed in default configuration (degrees)
static constexpr float CorrectionAngle = -45.;
void _fill_surface_single(const FillParams& params,
unsigned int thickness_layers,
const std::pair<float, Point>& direction,
ExPolygon expolygon,
Polylines& polylines_out) override;
};
} // namespace Slic3r
#endif // slic3r_FillTpmsD_hpp_

View file

@ -383,6 +383,7 @@ coordf_t Layer::get_sparse_infill_max_void_area()
case ipRectilinear:
case ipLine:
case ipGyroid:
case ipTpmsD:
case ipAlignedRectilinear:
case ipOctagramSpiral:
case ipHilbertCurve:

View file

@ -146,6 +146,7 @@ static t_config_enum_values s_keys_map_InfillPattern {
{ "triangles", ipTriangles },
{ "tri-hexagon", ipStars },
{ "gyroid", ipGyroid },
{ "tpmsd", ipTpmsD },//TpmsD from CrealityPrint
{ "honeycomb", ipHoneycomb },
{ "adaptivecubic", ipAdaptiveCubic },
{ "monotonic", ipMonotonic },
@ -158,7 +159,7 @@ static t_config_enum_values s_keys_map_InfillPattern {
{ "supportcubic", ipSupportCubic },
{ "lightning", ipLightning },
{ "crosshatch", ipCrossHatch},
{ "quartercubic", ipQuarterCubic}
{ "quartercubic", ipQuarterCubic},
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InfillPattern)
@ -2385,6 +2386,7 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("triangles");
def->enum_values.push_back("tri-hexagon");
def->enum_values.push_back("gyroid");
def->enum_values.push_back("tpmsd");
def->enum_values.push_back("honeycomb");
def->enum_values.push_back("adaptivecubic");
def->enum_values.push_back("alignedrectilinear");
@ -2405,6 +2407,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("Triangles"));
def->enum_labels.push_back(L("Tri-hexagon"));
def->enum_labels.push_back(L("Gyroid"));
def->enum_labels.push_back(L("TPMS-D"));
def->enum_labels.push_back(L("Honeycomb"));
def->enum_labels.push_back(L("Adaptive Cubic"));
def->enum_labels.push_back(L("Aligned Rectilinear"));

View file

@ -58,7 +58,7 @@ enum AuthorizationType {
};
enum InfillPattern : int {
ipConcentric, ipRectilinear, ipGrid, ip2DLattice, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
ipConcentric, ipRectilinear, ipGrid, ip2DLattice, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipTpmsD, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal,
ipLightning, ipCrossHatch, ipQuarterCubic,
ipCount,