Overview

The Additive class is used to create additive manufacturing solutions. The first solution is for Powder Bed Fusion.

PBF solutions are defined for the geometry in a STEP file. Each solution is defined as a plan that operates in four stages.

The first three stages of the process are shown in the figure below. Note the small footprint of the result, about 14K of data. The solution defines how to make scan paths using a reference algorithm defined by the ISO 10303 standard. The scan paths would have a much larger data volume if they were stored, typically hundreds of gigabytes. The scan paths do not need to be stored because a 3D printer can use the reference algorthm to make the paths on demand.

Example 1

The following example reads a STEP file and defines a simple process for a part that only needs one region.

static void Example1()
{
    Additive pbf = new Additive();
    pbf.OpenSTEP("NIST_STEP_Test_v1.stp");		    // Read the STEP fike
    pbf.PBFSlice("Test 1 part", 0.05, 90);	            // slice thickness = 0.05mm rotation = 90 degree
    pbf.PBFSliceInitialRotationPutDEG(45.0);	            // first slice at 45 degree
    long reg1 = pbf.PBFInskinRegion();			    // part does NOT need upskin or downskin
    long op1 = pbf.PBFStripe(reg1, 10, 0.12);               // width=10mm, overlap=0.12mm
    long op2 = pbf.PBFPreContour(op1, 0.08);	            // contour 1 offset=0.08mm
    long op3 = pbf.PBFPreContour(op1, 0.16);                // contour 2 offset=0.16mm
    long infill = pbf.PBFInfill(op1, 0.14, 0.08);           // hatch offset=0.14mm, hatch=0.08mm
    pbf.PBFProcess(infill, 0.25, 1000, 0.08);		    // infill power=0.25kw, speed=1000mmps, beam=0.08mm
    pbf.PBFProcess(op2, 0.09, 300, 0.08);		    // contour 1 power=0.09kw, speed=300mmps, beam=0.08mm
    pbf.PBFProcess(op3, 0.08, 300, 0.08);		    // contour 2 power=0.08kw, speed=300mmps, beam=0.08mm 
    pbf.PBFMaterialSet("chunky", "chocolate standard");     // set these to "real" values
    pbf.SaveSTEP("NIST_STEP_Test_v1_process.stpnc");	    // save the process
}
NIST_STEP_Test_v1.stp

NIST_STEP_Test_v1_process.stpnc

Example 2

The following example reads a STEP file and defines a process for a part that has two regions. The core of the part is made using a process similar to example 1. A second process is defined for those regions that are close to any surface that slopes at an angle greater than 48 degrees. This process reduces the heat to avoid over melting powder that is within three layers of the down slope.

static void Example2()
{
    Additive pbf = new Additive();
    pbf.OpenSTEP("TMmini_OQ_block_v2.stp");		    // Read the STEP fike
    pbf.PBFSlice("Test 2 part", 0.1, 90);	            // slice thickness = 0.05mm rotation = 90 degree

    long reg1 = pbf.PBFInskinRegion();			    // inskin uses a stripe operation
    long op_st = pbf.PBFStripe("inskin", 10, 0.12);         // width=10mm overlap=0.12mm
    long op_c1 = pbf.PBFPreContour("inskin", 0.08);	    // contour 1 offset=0.08mm
    long op_c2 = pbf.PBFPreContour("inskin", 0.16);         // contour 2 offset=0.16mm
    long op_i1 = pbf.PBFInfill("inskin", 0.14, 0.12);       // hatch offset=0.14mm, space=0.12mm
    pbf.PBFInfillDirectionPutDegree(op_st, 45);             // stripe vector direction = 45 degree
    pbf.PBFProcess(op_i1, 0.27, 1000, 0.08);		    // stripe infill power=0.27kw, speed=1000mmps, beam=0.08mm
    pbf.PBFProcess(op_c1, 0.136, 500, 0.08);		    // contour 1 power=0.135kw, speed=500mmps, beam=0.08mm
    pbf.PBFProcess(op_c2, 0.128, 500, 0.08);                // contour 2 power=0.120kw, speed=500mmps, beam=0.08mm 
    pbf.PBFContourSetAlternate(op_c1);                      // Alternate direction of contour by slice (this is default)
    pbf.PBFContourSetAlternate(op_c2);                      // Alternate direction of contour by slice (this is default)

    long reg2 = pbf.PBFDownskinRegion(48, 3);               // downskin has 3 layers, downskin limit is 48 degree
    long op_mea = pbf.PBFMeander (reg2);                    // downskin uses a meander operation
    long op_i2= pbf.PBFInfill(reg2, 0.1, 0.1);              // hatch offset=0.1mm, space=0.1mm
    pbf.PBFInfillDirectionPutDegree(reg2, 135);             // stripe vector direction = 135 degree
    pbf.PBFProcess(op_i2, 0.135, 1000, 0.08);               // meander infill power=0.120kw, speed=500mmps, beam=0.08mm 
    pbf.PBFRegionMinAreaPutMM2(reg2, 0.04);                 // minimum size allowed for region

    pbf.PBFMaterialSet("chunky", "chocolate standard");     // set these to "real" values
    pbf.SaveSTEP("TMmini_OQ_block_v2_process.stpnc");	    // save the process
}
TMmini_OQ_block_v2.stp

TMmini_OQ_block_v2_process.stpnc

Print STEP-NC

The next example reads a STEP-NC file and prints the parameters of its defined processes. The print starts by listing the parameters of the slice definition. Next for each region it lists the constraints that defines the region followed by the process selected to manufacture that region. The pre-contours are listed first. The infill is described next. The post-contours are listed last.

static void PrintSTEPNC(string file_name)
{
    Additive pbf = new Additive();
    pbf.OpenSTEPNC(file_name);
    double thick = pbf.PBFSliceThicknessGetMM();
    double rot = pbf.PBFSliceRotationGetDEG();
    double start = pbf.PBFSliceInitialRotationGetDEG();
    Console.WriteLine(file_name);
    Console.WriteLine("Slice: Thickness = " + thick + "mm Rotation = " + rot + " degrees");
    if (start != 0)
        Console.WriteLine("Initial rotation = " + start + " degrees");

    long region_count = pbf.PBFRegionCount();
    for (int rc = 0; rc < region_count; rc++)
    {
        string type = pbf.PBFRegionTypeGet(rc + 1);
        if (type == "inskin")
        {
            Console.WriteLine("Region " + (rc + 1) + " is inskin:");
        }
        else if (type == "downskin")
        {
            double down_angle = pbf.PBFRegionDownskinAngleGetDeg("downskin");
            long layer_count = pbf.PBFRegionLayerCountGet("downskin");
            double min_area = pbf.PBFRegionMinAreaGetMM2("downskin");
            Console.WriteLine("Region " + (rc + 1) + " is downskin for " + layer_count + " Layers at angle " + down_angle + " degrees:");
            if (min_area != 0)
                Console.WriteLine("\tMinimum Area = " + min_area + " mms");
        }
        else if (type == "upskin")
        {
            double down_angle = pbf.PBFRegionDownskinAngleGetDeg("upskin");
            long layer_count = pbf.PBFRegionLayerCountGet("upskin");
            double min_area = pbf.PBFRegionMinAreaGetMM2("upskin");
            Console.WriteLine("Region " + (rc + 1) + " is upskin for " + layer_count + " Layers at angle " + down_angle + " degrees:");
            if (min_area != 0)
                Console.WriteLine("\tMinimum Area = " + min_area + " mms");
        }
        else
        {
            Console.WriteLine("Region " + (rc + 1) + " is unknown:");
        }

        long op2d1 = pbf.PBFRegionOperationGet(rc + 1);
        long pre_count = pbf.PBFPreContourCount(op2d1);
        for (int i = 1; i <= pre_count; i++)
        {
            Console.WriteLine("Pre Contour " + i + ":");
            long cn = pbf.PBFPreContourGet(op2d1, i);
            double cn_offset = pbf.PBFContourOffsetGetMM(cn);
            if (pbf.PBFContourSense(cn) == "clockwise")
                Console.WriteLine("\tClockwise offset = " + cn_offset + "mm");
            else
                Console.WriteLine("\tOffset = " + cn_offset + "mm");

            if (pbf.PBFProcessTechnologyGet(cn) != 0)
            {
                double power = pbf.PBFProcessPowerGetKW(cn);
                double diameter = pbf.PBFProcessDiameterGetMM(cn);
                double speed = pbf.PBFProcessSpeedGetMMPS(cn);
                Console.WriteLine("\tPower = " + power + "kw speed = " + speed + " mmps diameter = " + diameter + "mm");
            }
            else
                Console.WriteLine("\tNO CONTOUR TECHNOLOGY");
        }
        if (pre_count == 0)
            Console.WriteLine("NO PRE-CONTOURs IN REGION");

        string op_type = pbf.PBFRegionOperationTypeGet(rc + 1);
        if (op_type == "stripe")
        {
            double width = pbf.PBFStripeWidthGetMM(op2d1);
            double overlap = pbf.PBFStripeOverlapGetMM(op2d1);
            double direction = pbf.PBFInfillDirectionGetDegree(op2d1);
            Console.WriteLine("Stripe:");
            if (direction != 0)
                Console.WriteLine("\tInfill direction = " + direction + " degree");
            Console.WriteLine("\tWidth = " + width + "mm, Overlap = " + overlap + " mm");
        }
        else if (op_type == "chess")
        {
            double width = pbf.PBFChessWidthGetMM(op2d1);
            double length = pbf.PBFChessLengthGetMM(op2d1);
            double direction = pbf.PBFInfillDirectionGetDegree(op2d1);
            Console.WriteLine("Chess:");
            if (direction != 0)
                Console.WriteLine("\tInfill direction = " + direction + " degree");
            Console.WriteLine("\tWidth = " + width + "mm" + "Length = " + length + " mm");
        }
        else if (op_type == "meander")
        {
            Console.WriteLine("Meander:");
            double direction = pbf.PBFInfillDirectionGetDegree(op2d1);
            if (direction != 0)
                Console.WriteLine("\tInfill direction = " + direction + " degree");
        }
        else
            Console.WriteLine("\tNO OPERATION DEFINED REGION");

        long fill1 = pbf.PBFInfillGet(op2d1);
        double space = pbf.PBFInfillSpaceGetMM(fill1); // REG or INFILL
        double offset = pbf.PBFInfillOffsetGetMM(fill1);
        Console.WriteLine("Infill:");
        Console.WriteLine("\tSpace = " + space + " mm offset = " + offset + " mm");

        if (pbf.PBFProcessTechnologyGet(fill1) != 0)
        {
            double power = pbf.PBFProcessPowerGetKW(fill1);
            double diameter = pbf.PBFProcessDiameterGetMM(fill1);
            double speed = pbf.PBFProcessSpeedGetMMPS(fill1);
            Console.WriteLine("\tPower = " + power + "kw speed = " + speed + " mmps diameter = " + diameter + "mm");
        }
        else
            Console.WriteLine("\tNO FILL TECHNOLOGY");

        long post_count = pbf.PBFPostContourCount(op2d1);
        for (int i = 1; i <= post_count; i++)
        {
            Console.WriteLine("Post Contour " + i + ":");
            long cn = pbf.PBFPostContourGet(op2d1, i);
            double cn_offset = pbf.PBFContourOffsetGetMM(cn);
            if (pbf.PBFContourSense(cn) == "clockwise")
                Console.WriteLine("\tClockwise offset = " + cn_offset + "mm");
            else if (pbf.PBFContourSense(cn) == "counter_clockwise")
                Console.WriteLine("\tCounter Clockwise offset = " + cn_offset + "mm");
            else
                Console.WriteLine("\tOffset = " + cn_offset + "mm");

            if (pbf.PBFProcessTechnologyGet(cn) != 0)
            {
                double power = pbf.PBFProcessPowerGetKW(cn);
                double diameter = pbf.PBFProcessDiameterGetMM(cn);
                double speed = pbf.PBFProcessSpeedGetMMPS(cn);
                Console.WriteLine("\tPower = " + power + "kw speed = " + speed + " mmps diameter = " + diameter + "mm");
            }
            else
                    Console.WriteLine("\tNO CONTOUR TECHNOLOGY");
        }
        if (post_count == 0)
            Console.WriteLine("NO POST-CONTOURs IN REGION");

        Console.WriteLine();
    }
}
Print Example 1

Print Example 2

PBFSlice()

System::Int64 PBFSlice (
	System::String^ solution_name,
	double slice_thickness_mm,
	double interslice_rotation_degree
	);

The PBFSlice() function defines the thickness and orientation of each slice. Starting at the base, the geometry is sliced into layers of the given thickness. To reduce stress, each slice is given a different orientation by the interslice rotation. Typical values for the rotation are 67 degrees and 47 degrees so that no two slices have the same rotation. If it matters the initial rotation can be set non-zero using the initial slice rotation put function.

Arguments

solution name
Name for the solution.
slice thickness
The thickness of each slice.
interslice rotation
The rotation increment for each layer.

Result

Related Functions

Common Errors

PBFInfillRegion()/PBFDownskinRegion()/PBFUpskinRegion()

System::Int64 PBFInfillRegion (
	);

System::Int64 PBFDownskinRegion (
	double high_above_angle_degree,
	System::Int64 layer_count
	);

System::Int64 PBFUpskinRegion (
	double high_below_angle_degree,
	System::Int64 layer_count
	);

Three kinds of regions can be defined. The infill region describes the process used for the majority of the part. The downskin region describe the process for surfaces that overhang. The upskin region describes the process for surfaces at the top of the part. For many parts there will only be an infill region. A downskin region is quite common because of melting issues. The upskin region is rare.

Arguments

high_above_angle_degree
The angle above the horizontal for a downskin surface. If the angle exceeds this value then the surface is not a downskin.
high_below_angle_degree
The angle below the horizontal for a upskin surface. If the angle exceeds this value then the surface is not an upskin.
layer count
The number of layers above the skin where the process applies (or below for an upskin).

Result

Related Functions

Common Errors

PBFStripe()

System::Int64 PBFStripe (
        System::Int64 region_id,	// or System::String^ region_type
        double stripe_width_mm,
        double offset_mm,
        double overlap_mm, 
        double hatch_space_mm 
	);

The PBFStripe() function defines how a region is filled. The region is divided into stripes with the stripe width. The offset defines a border between the part edges and the first stripe. The overlap defines an overrun between consecutive stripes. The hatch space defines the distance between scan paths within the stripe.

Arguments

region id
The identity of the region being filled.
region type
The identity of the region given as a name ("inskin", "downskin, or "upskin").
stripe width
The width of each stripe. The stripes are laid so that the left border of one is on the y-axis of the slice.
offset
An offset from the part edge that will not be filled by a stripe. The area of the offset may be filled by a contour.
overlap
An overlap between stripes to ensure seamless melting.
hatch space
The distance between scan paths within a stripe.

Result

Related Functions

Common Errors

PBFChess()

System::Int64 PBFChess (
        System::Int64 region_id,	// or System::String^ region_type
        double rectangle_width_mm,
        double rectangle_length_mm,
        double chess_overlap_mm, 
	);

The PBFChess() function defines how a region is filled. The region is divided into chess squares with a width and length. The overlap defines an overrun between consecutive squares.

Arguments

region id
The identity of the region being filled.
region type
The identity of the region given as a name ("inskin", "downskin, or "upskin").
rectangle width
The width of each rectangle. The squares are laid so that the left border of one is on the y-axis of the slice.
rectangle length
The height of each rectangle. The squares are laid so that the the bottom border of one is on the x-axis.
chess overlap
An overlap between squares on the same row and/or column.

Result

Related Functions

Common Errors

PBFMeander()

System::Int64 PBFMeander (
        System::Int64 region_id,	// or System::String^ region_type
	);

The PBFMeander() function defines a region that is filled without making any stripes or chess squares.

Arguments

region id
The identity of the region being filled.
region type
The identity of the region given as a name ("inskin", "downskin, or "upskin").

Result

Related Functions

Common Errors

PBFInfill()

System::Int64 PBFInfill (
        System::Int64 region_id,	// or System::String^ region_type
        double hatch_offset_mm,
        double hatch_space_mm 
	);

The PBFInfill() function defines how hatches are defined for an infill. The hatch offset defines an offset between the hatch and the edge of the part. The hatch space defines the distance between consecutive scan paths.

Arguments

region id
The identity of the region being filled.
region type
The identity of the region given as a name ("inskin", "downskin, or "upskin").
hatch offset
An offset from the part edge that will not be filled. The area of the offset may be filled by a contour.
hatch space
The distance between consecutive scan paths.

Result

Related Functions

Common Errors

PBFPrecontour()/PBFPostcontour()

System::Int64 PBFPreContour() (
        System::Int64 region_id,	// or System::String^ region_type
        double offset_mm 
	);

System::Int64 PBFPostContour() (
        System::Int64 region_id,	// or System::String^ region_type
        double offset_mm 
	);

The PBFxxxContour() functions define how a contour is laid around the part edges within a region. The offset defines a border between the part edge and the contour. No contour is laid for edges of the region that are not on borders of the part.

The PBFPreContour() function defines contours scanned before the infill.

The PBFPostContour() function defines contours scanned after the infill.

Arguments

region id
The identity of the region being contoured.
region type
The identity of the region given as a name ("inskin", "downskin, or "upskin").
offset
An offset between the part edge and the contour. The area of the offset is filled by the contour.

Result

Related Functions

Common Errors

PBFProcess()

System::Int64 Additive::PBFProcess (
        System::Int64 op_id,
        double power_kw, 
        double speed_mmps, 
        double beam_diameter_mm    
    )

The PBFProcess() function defines the process parameters that are to be used when scanning an infill or contour. These parameters are chosen to ensure the process produces the correct melting to fuse the part. Too much heat will cause the powder to boil leaving voids in the material. Too little heat will allow the powder to stay solid. The conductivity of the material changes as it melts, and is less efficient near the part borders and overhangs.

Arguments

op_id
The identity of the infill or contour that is to be given this process.
power kw
The power that is to be used to melt the pool during this scanning process.
speed mmps
The speed of the beam while it is melting the pool.
beam diameter mm
The diameter (focus) of the beam while it is performing the melting.

Result

Related Functions

Common Errors

PBFMaterial()

System::Int64 Additive::PBFMaterialSet (
	System::String^ material_name,
	System::String^ standard_name
    )

System::String^ Additive::PBFMaterialGet (
    )

System::String^ Additive::PBFMaterialStandardGet (
    )

The PBFMaterial() function defines the material assumed by the process. The process expert must understand the characteristics of the material to ensure proper melting.

Arguments

material name
The name of the material assumed by the melting process.
standard name
The name of the standard that defines the characteristics of the material.

Result

Related Functions

Common Errors

PBFPlacement()

void Additive::PBFPlacement (
        double x, y, z, 
        double i, j, k, 
        double a, b, c    
    )

The PBFPlacement() function changes the placement of the part to the correct position for the melting process. The part will have a native placement and orientation defined by a CAD system. The placement function changes it to the location and orientation required by the manufacturing process.

Arguments

x, y, z
The new origin.
i, j, k
The new up (Z) direction.
a, b, c
The new X direction.

Result

Related Functions

Common Errors

PBFRead/Write()

void Additive::OpenSTEP(
        System::String^ filename
)

void Additive::SaveSTEP(
        System::String^ filename
)

The OpenSTEP() function reads the STEP file that will be given the fusion process. The SaveSTEP() function writes the STEP file containing the new process. The two files may have the same name because the one with the melting process will be given the extension ".stpnc". The wider library referenced in the banner includes many options for reading and writing the STEP files. The confoguration used for PBF includes many comments to help you understand the generated data.

Arguments

filename
The name of the STEP or STEP-NC file.

Result

Related Functions

Common Errors