This module allows you to encode data in ISO 10303-21 (STEP file) format.
Here is a sample STEP file (adapted from Wikipedia):
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('A minimal AP214 example with a single part'),'2;1');
FILE_NAME('demo','2003-12-27T11:57:53',('Lothar Klein'),('LKSoft'),' ','IDA-STEP',' ');
FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 2 1 1}'));
ENDSEC;
DATA;
#10=ORGANIZATION('O0001','LKSoft','company');
#11=PRODUCT_DEFINITION_CONTEXT('part definition',#12,'manufacturing');
#12=APPLICATION_CONTEXT('mechanical design');
#13=APPLICATION_PROTOCOL_DEFINITION('','automotive_design',2003,#12);
#14=PRODUCT_DEFINITION('0',$,#15,#11);
#15=PRODUCT_DEFINITION_FORMATION('1',$,#16);
#16=PRODUCT('A0001','Test Part 1','',(#18));
#17=PRODUCT_RELATED_PRODUCT_CATEGORY('part',$,(#16));
#18=PRODUCT_CONTEXT('',#12,'');
#19=APPLIED_ORGANIZATION_ASSIGNMENT(#10,#20,(#16));
#20=ORGANIZATION_ROLE('id owner');
ENDSEC;
END-ISO-10303-21;
To create this file using this package, you could write
module Example exposing (..)
import Step.Encode as Encode
stepFile : String
stepFile =
let
header =
{ description = [ "A minimal AP214 example with a single part" ]
, implementationLevel = "2;1"
, fileName = "demo"
, timeStamp = "2003-12-27T11:57:53"
, author = [ "Lothar Klein" ]
, organization = [ "LKSoft" ]
, preprocessorVersion = " "
, originatingSystem = "IDA-STEP"
, authorization = " "
, schemaIdentifiers = [ "AUTOMOTIVE_DESIGN { 1 0 10303 214 2 1 1}" ]
}
applicationContext =
Encode.entity "APPLICATION_CONTEXT"
[ Encode.string "mechanical design"
]
applicationProtocolDefinition =
Encode.entity "APPLICATION_PROTOCOL_DEFINITION"
[ Encode.string ""
, Encode.string "automotive_design"
, Encode.int 2003
, Encode.referenceTo applicationContext
]
product =
Encode.entity "PRODUCT"
[ Encode.string "A0001"
, Encode.string "Test Part 1"
, Encode.string ""
, Encode.list Encode.referenceTo
[ Encode.entity "PRODUCT_CONTEXT"
[ Encode.string ""
, Encode.referenceTo applicationContext
, Encode.string ""
]
]
]
productDefinition =
Encode.entity "PRODUCT_DEFINITION"
[ Encode.string "0"
, Encode.null
, Encode.referenceTo <|
Encode.entity "PRODUCT_DEFINITION_FORMATION"
[ Encode.string "1"
, Encode.null
, Encode.referenceTo product
]
, Encode.referenceTo <|
Encode.entity "PRODUCT_DEFINITION_CONTEXT"
[ Encode.string "part definition"
, Encode.referenceTo applicationContext
, Encode.string "manufacturing"
]
]
productRelatedProductCategory =
Encode.entity "PRODUCT_RELATED_PRODUCT_CATEGORY"
[ Encode.string "part"
, Encode.null
, Encode.list Encode.referenceTo [ product ]
]
appliedOrganizationAssignment =
Encode.entity "APPLIED_ORGANIZATION_ASSIGNMENT"
[ Encode.referenceTo <|
Encode.entity "ORGANIZATION"
[ Encode.string "O0001"
, Encode.string "LKSoft"
, Encode.string "company"
]
, Encode.referenceTo <|
Encode.entity "ORGANIZATION_ROLE"
[ Encode.string "id owner"
]
, Encode.list Encode.referenceTo [ product ]
]
in
Encode.file header
[ applicationContext
, applicationProtocolDefinition
, productDefinition
, productRelatedProductCategory
, appliedOrganizationAssignment
]
Note that entities can be declared directly 'inside' other entities where this
makes sense, and not all entities have to be explicitly listed in the
Encode.file
call, only top-level ones. Any entities directly or indirectly
referenced by the listed entities will also be included in the output. Entity
IDs are automatically generated and entities may be written out in arbitrary
order.
file : Step.Types.Header -> List Step.Types.Entity -> String
Build a string representing a complete STEP file from a header and a list of entities. Entities will be assigned integer IDs automatically, and nested entities (entities that reference other entities) will be 'flattened' into separate entities referring to each other by their automatically-generated IDs.
Note that it is not actually necessary to list all entities explicitly, only top-level ones; any entities that are referenced by entities in the given list will also get included in the output.
entity : String -> List Step.Types.Attribute -> Step.Types.Entity
Construct a single simple entity with the given type and attributes. The
type name will be capitalized if necessary. An IfcDirection
representing the positive Y direction in 3D could be created using
direction =
Encode.entity "IFCDIRECTION"
[ Encode.list Encode.float [ 0, 1, 0 ]
]
which might get encoded as #1=IFCDIRECTION((0.,1.,0.));
.
If a given entity is only referred to by a single other entity, you can create it directly inside the definition of the parent entity. For example, to create entity #121 from this AP214 example, you could use
Encode.entity "AXIS2_PLACEMENT_3D"
[ Encode.string ""
, Encode.referenceTo <|
Encode.entity "CARTESIAN_POINT"
[ Encode.string ""
, Encode.list Encode.float [ 20, 7.5, 0 ]
]
, Encode.referenceTo <|
Encode.entity "DIRECTION"
[ Encode.string ""
, Encode.list Encode.float [ 1, 0, 0 ]
]
, Encode.referenceTo <|
Encode.entity "DIRECTION"
[ Encode.string ""
, Encode.list Encode.float [ 0, 0, -1 ]
]
]
When actually encoded to a STEP file, this will get converted into four separate entities, with the top-level entity referring to the other three by their automatically-generated IDs, something like:
#1=AXIS2_PLACEMENT_3D('',#2,#3,#4);
#2=CARTESIAN_POINT('',(20.,7.5,0.));
#3=DIRECTION('',(1.,0.,0.));
#4=DIRECTION('',(0.,0.,-1.));
complexEntity : List Step.Types.SubEntity -> Step.Types.Entity
Construct a single 'complex entity'; for example
Encode.complexEntity
[ Encode.subEntity "A" [ Encode.int 1 ]
, Encode.subEntity "B"
[ Encode.int 2
, Encode.string "three"
]
, Encode.subEntity "C" [ Encode.enum "FOUR" ]
]
will be encoded as
#1=(A(1)B(2,'three')C(.FOUR.));
subEntity : String -> List Step.Types.Attribute -> Step.Types.SubEntity
Encode a sub-entity that will become part of a complex entity, with the given type name and attributes.
derivedValue : Step.Types.Attribute
The special 'derived value' attribute.
null : Step.Types.Attribute
The special 'null value' attribute.
optional : (a -> Step.Types.Attribute) -> Maybe a -> Step.Types.Attribute
Encode a Maybe
either using the given decoder if it is a Just value
, or
as null if it is Nothing
.
bool : Basics.Bool -> Step.Types.Attribute
Construct a Boolean-valued attribute.
int : Basics.Int -> Step.Types.Attribute
Construct an integer-valued attribute.
float : Basics.Float -> Step.Types.Attribute
Construct a real-valued attribute.
string : String -> Step.Types.Attribute
Construct a string-valued attribute.
referenceTo : Step.Types.Entity -> Step.Types.Attribute
Construct a reference to another STEP entity (will end up being encoded
using an integer ID in the resulting STEP file, e.g. #123
).
enum : String -> Step.Types.Attribute
Construct an attribute that refers to an enumeration value defined in an
EXPRESS schema. Enumeration values are always encoded as all-caps with leading
and trailing periods, like .STEEL.
.
This function will capitalize and add periods if necessary, so both
Encode.enum "steel"
and Encode.enum ".STEEL."
will be encoded as
.STEEL.
.
binaryData : Bytes.Encode.Encoder -> Step.Types.Attribute
Construct an attribute from a blob of binary data given as an encoder.
Note that since Elm only supports byte-aligned binary data, there is no way to create (for example) a blob of binary data exactly 5 bits in size even though that is supported by the STEP standard.
list : (a -> Step.Types.Attribute) -> List a -> Step.Types.Attribute
Construct an attribute which is itself a list of other attributes. You provide a list of values and a function to convert each of those values to an attribute (which will usually be one of the attribute construction functions in this module!). For example, to construct an attribute which is a list of floats:
Encode.list Encode.float [ 0, 1, 0 ]
To construct a list of references to various entities:
Encode.list Encode.referenceTo
[ firstEntity
, secondEntity
, thirdEntity
]
In the odd case where you already have a List Attribute
, you can use Elm's
built-in identity
function as the first argument:
Encode.list identity
[ firstAttribute
, secondAttribute
, thirdAttribute
]
tuple2 : (a -> Step.Types.Attribute) -> ( a, a ) -> Step.Types.Attribute
Encode a tuple of two values as a list using the given encoding function.
tuple3 : (a -> Step.Types.Attribute) -> ( a, a, a ) -> Step.Types.Attribute
Encode a tuple of three values as a list using the given encoding function.
Typed attributes are sometimes needed when dealing with SELECT types.
boolAs : String -> Basics.Bool -> Step.Types.Attribute
Construct a type-tagged Boolean-valued attribute.
intAs : String -> Basics.Int -> Step.Types.Attribute
Construct a type-tagged integer-valued attribute.
floatAs : String -> Basics.Float -> Step.Types.Attribute
Construct a type-tagged float-valued attribute.
stringAs : String -> String -> Step.Types.Attribute
Construct a type-tagged string-valued attribute.
enumAs : String -> String -> Step.Types.Attribute
Construct a type-tagged enumeration attribute.
binaryDataAs : String -> Bytes.Encode.Encoder -> Step.Types.Attribute
Construct a type-tagged binary-valued attribute.
listAs : String -> (a -> Step.Types.Attribute) -> List a -> Step.Types.Attribute
Construct a type-tagged list attribute.
typedAttribute : String -> Step.Types.Attribute -> Step.Types.Attribute
Construct a generic type-tagged attribute. In most cases it will be simpler
to use one of the specific functions such as floatAs
or enumAs
.