/* * Copyright (c) 1991-2023 by STEP Tools Inc. * All Rights Reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation is hereby granted, provided that this copyright * notice and license appear on all copies of the software. * * STEP TOOLS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. STEP TOOLS * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. * * Author: Dave Loffredo (loffredo@steptools.com) */ #include #include #include #include "geometry_utils.h" #include "context_utils.h" #include "unit_utils.h" // The ROUNDHOLE sample program demonstrates how to create a STEP // round hole feature. This program builds a sample product and then // attaches a round hole feature to it. The program just creates the // parametric description for the feature (circular profile swept // along a linear path) and gives it a flat bottom condition. // // We do not have any CAD geometry in this example, but the code also // shows how to associate a feature with advanced_face instances on // the product geometry. // This program creates the data set and saves it as a STEP Part 21 // file called "output_file.stp". This is a text file, so you can // look at it with a text editor or the STEP Part 21 file browser to // see how the information is represented. stp_product_definition_shape * make_sample_product( RoseDesign * d ); // Create a complete round hole feature stp_instanced_feature * make_round_hole( stp_product_definition_shape * pds, const char * feat_name, double diameter, double depth, double x, double y, double z, // top center of hole double i, double j, double k, // direction pointing into hole stp_named_unit * len_unit ); // The various components of the feature stp_circular_closed_profile * make_circular_profile( double diameter, stp_axis2_placement_3d * origin, stp_named_unit * len_unit ); stp_path_feature_component * make_linear_path( double depth, stp_axis2_placement_3d * origin, stp_named_unit * len_unit ); stp_hole_bottom * make_flat_hole_bottom( RoseDesign * d ); // Some utility functions to help with common tasks stp_representation * make_shape_rep_with_params( stp_product_definition_shape * pds, stp_named_unit * len_unit ); stp_representation * make_explicit_shape_rep( stp_product_definition_shape * pds, stp_named_unit * len_unit ); stp_measure_representation_item * make_length_measure( double len, stp_named_unit * len_unit ); stp_product_definition_shape * make_feature_component_definition( RoseDesign * d ); stp_representation_context * make_common_context( stp_named_unit * len_unit ); int main(int /*argc*/, char** /*argv*/) { stplib_init(); // initialize STEP class library rose_p28_init(); // support xml read/write /* Create a RoseDesign to hold the instance data */ const char * output_name = "output_file"; RoseDesign * design = new RoseDesign (output_name); // Declare it as an AP214 file stplib_put_schema (design, stplib_schema_ap214); // Give the design some Part 21 header information design-> initialize_header(); design-> header_name()-> originating_system ("Round Hole Demo"); design-> header_description()-> description ()-> add ("Round Hole Sample File"); // Make a product to attach the hole to stp_product_definition_shape * pds = make_sample_product (design); // define hole feature make_round_hole( pds, "first hole", 1, 3, // 1in dia, 3in deep 1,2,3, // with top at (1,2,3) 0,0,-1, // going in the (0,0,-1) direction make_inch_unit (design) ); // Uncomment the following to write as zip compressed P28 XML // rather than Part 21 ASCII. You can also write uncompressed XML // by changing the format string to "p28-raw" // // design-> format ("p28"); design-> save(); return 0; } stp_instanced_feature * make_round_hole( stp_product_definition_shape * pds, const char * feat_name, double diameter, double depth, double x, double y, double z, // top center of hole double i, double j, double k, // direction pointing into hole stp_named_unit * len_unit ) { if (!pds) return 0; RoseDesign * d = pds-> design(); // make the round hole instance (a shape aspect subtype) so that // we can attach it to the product. stp_round_hole_and_instanced_feature * hole = pnewIn(d) stp_round_hole_and_instanced_feature; hole-> of_shape(pds); hole-> stp_shape_aspect::name(feat_name? feat_name: ""); hole-> stp_characterized_object::name(""); hole-> product_definitional(1); // Give the hole a product_definition_shape for the components and // placement to attach to. // stp_product_definition_shape * hole_pds = pnewIn(d) stp_product_definition_shape; hole_pds-> name (""); hole_pds-> definition (pnewIn(d) stp_characterized_definition); hole_pds-> definition ()-> _characterized_object (hole); // Add the feature orientation. It is an axis placement named // "orientation" in a special representation subtype. This is // also shared with the profiles and paths as their origin too. // stp_representation * rep = make_shape_rep_with_params (hole_pds, len_unit); stp_axis2_placement_3d* origin = pnewIn(d) stp_axis2_placement_3d; origin-> name ("orientation"); origin-> location (pnewIn(d) stp_cartesian_point); origin-> location()-> name(""); origin-> location()-> coordinates()->add(x); origin-> location()-> coordinates()->add(y); origin-> location()-> coordinates()->add(z); origin-> axis (pnewIn(d) stp_direction); origin-> axis()-> name(""); origin-> axis()-> direction_ratios()->add(i); origin-> axis()-> direction_ratios()->add(j); origin-> axis()-> direction_ratios()->add(k); // Add it to the representation rep-> items()-> add (origin); // Make the profile and path, then attach them to the hole through // an occurance shape aspect and a shape_defining_relationship is // used to link the feature with a profile or path component that // sweeps out its shape. // stp_shape_aspect * occ_sa; stp_shape_aspect_relationship * occ_rel; // make the circular profile component stp_circular_closed_profile * prof = make_circular_profile( diameter, origin, len_unit ); occ_sa = pnewIn(d) stp_shape_aspect; occ_sa-> name (""); occ_sa-> description ("diameter occurrence"); occ_sa-> product_definitional (0); occ_sa-> of_shape (hole_pds); occ_rel = pnewIn(d) stp_shape_defining_relationship; occ_rel-> name ("diameter"); occ_rel-> description ("profile usage"); occ_rel-> related_shape_aspect (occ_sa); occ_rel-> relating_shape_aspect (prof); // make the linear path component stp_path_feature_component * path = make_linear_path ( depth, origin, len_unit ); occ_sa = pnewIn(d) stp_shape_aspect; occ_sa-> name (""); occ_sa-> description ("hole depth occurrence"); occ_sa-> product_definitional (0); occ_sa-> of_shape (hole_pds); occ_rel = pnewIn(d) stp_shape_defining_relationship; occ_rel-> name ("hole depth"); occ_rel-> description ("path feature component usage"); occ_rel-> related_shape_aspect (occ_sa); occ_rel-> relating_shape_aspect (path); // Make the hole bottom. Hole bottoms, tapers, and other auxllary // components are related using a different relationship subtype. // The "hole depth end" name indicates that the origin is at the // top of the hole and the path points into the hole. There is a // "hole depth start" string that indicates that the origin is at // the bottom of the hole with the placement pointing up and out // of the hole. // stp_hole_bottom * bot = make_flat_hole_bottom (d); occ_sa = pnewIn(d) stp_shape_aspect; occ_sa-> name (""); occ_sa-> description ("bottom condition occurrence"); occ_sa-> product_definitional (0); occ_sa-> of_shape (hole_pds); occ_rel = pnewIn(d) stp_feature_component_relationship; occ_rel-> name ("hole depth end"); occ_rel-> description ("hole bottom usage"); occ_rel-> related_shape_aspect (occ_sa); occ_rel-> relating_shape_aspect (bot); // The code above creates the parametric parts of the feature // description. It is also common to associate a feature with // advanced_face instances on the product geometry. We do not // have any geometry in this example, but the code below shows // how one would add explicit faces to a feature. // rep = make_explicit_shape_rep (hole_pds, len_unit); // rep-> items()-> add (face_1); // rep-> items()-> add (face_2); // etc. return hole; } // Create the complete circular profile for a round hole. By AP224 // usage, the profile uses the same placement as the hole feature. // stp_circular_closed_profile * make_circular_profile( double diameter, stp_axis2_placement_3d * origin, stp_named_unit * len_unit ) { if (!len_unit) return 0; RoseDesign * d = len_unit-> design(); stp_circular_closed_profile * prof = pnewIn(d) stp_circular_closed_profile; prof-> name (""); prof-> description (""); prof-> product_definitional (0); prof-> of_shape (make_feature_component_definition (d)); // Give the profile a product_definition_shape for properties to // attach to. // stp_product_definition_shape * prof_pds = pnewIn(d) stp_product_definition_shape; prof_pds-> name (""); prof_pds-> definition (pnewIn(d) stp_characterized_definition); prof_pds-> definition()->_shape_definition (pnewIn(d)stp_shape_definition); prof_pds-> definition()->_shape_definition()-> _shape_aspect (prof); // needs an origin and diameter stp_representation_item * dist = make_length_measure (diameter, len_unit); dist-> name ("diameter"); stp_representation * rep = make_shape_rep_with_params (prof_pds, len_unit); rep-> items()-> add (origin); rep-> items()-> add (dist); return prof; } // Create the linear path component for a round hole. By AP224 usage, // the path uses the same placement as the hole feature. // stp_path_feature_component * make_linear_path( double depth, stp_axis2_placement_3d * origin, stp_named_unit * len_unit ) { if (!len_unit) return 0; RoseDesign * d = len_unit-> design(); stp_path_feature_component * path = pnewIn(d) stp_path_feature_component; path-> name (""); path-> description ("linear"); path-> product_definitional (0); path-> of_shape (make_feature_component_definition (d)); // Give the travel pathdhole a product_definition_shape for // properties to attach to. // stp_product_definition_shape * path_pds = pnewIn(d) stp_product_definition_shape; path_pds-> name (""); path_pds-> definition (pnewIn(d) stp_characterized_definition); path_pds-> definition()->_shape_definition (pnewIn(d)stp_shape_definition); path_pds-> definition()->_shape_definition()-> _shape_aspect (path); // needs an origin and depth stp_representation_item * dist = make_length_measure (depth, len_unit); dist-> name ("distance"); stp_representation * rep = make_shape_rep_with_params (path_pds, len_unit); rep-> items()-> add (origin); rep-> items()-> add (dist); // needs a direction property. Just copy the axis direction from // the placement. stp_direction * dir = pnewIn(d) stp_direction; dir-> name(""); dir-> direction_ratios()-> add ( origin-> axis()-> direction_ratios()-> get(0) ); dir-> direction_ratios()-> add ( origin-> axis()-> direction_ratios()-> get(1) ); dir-> direction_ratios()-> add ( origin-> axis()-> direction_ratios()-> get(2) ); stp_direction_shape_representation * dir_rep = pnewIn(d) stp_direction_shape_representation; dir_rep-> name(""); dir_rep-> items()-> add(dir); dir_rep-> context_of_items (make_common_context(len_unit)); // Attach direction as a property. stp_product_definition_shape * dir_prop = pnewIn(d) stp_product_definition_shape; dir_prop-> name (""); dir_prop-> definition(pnewIn(d) stp_characterized_definition); dir_prop-> definition()->_shape_definition (pnewIn(d)stp_shape_definition); dir_prop-> definition()->_shape_definition()-> _shape_aspect (path); stp_property_definition_representation * dir_pdr = pnewIn(d) stp_property_definition_representation; dir_pdr-> definition (pnewIn(d) stp_represented_definition); dir_pdr-> definition ()-> _property_definition (dir_prop); dir_pdr-> used_representation (dir_rep); return path; } stp_hole_bottom * make_flat_hole_bottom( RoseDesign * d ) { stp_hole_bottom * bot = pnewIn(d) stp_hole_bottom; bot-> name (""); bot-> description ("flat"); bot-> product_definitional (0); bot-> of_shape (make_feature_component_definition (d)); return bot; } //------------------------------------------------------------ // Utility Functions // // CREATE A SAMPLE PRODUCT - Create a product and associated step // backbone objects that we will attach our feature to. // // The frame of reference context information is boilerplate, see // context_utils.cxx for the specifics. // stp_product_definition_shape * make_sample_product( RoseDesign * d ) { stp_product* pr = pnewIn(d) stp_product(); // Fill in the part number, name, and description. pr-> id ("1234-K789"); pr-> name ("widget"); pr-> description ("a fictional product"); pr-> frame_of_reference()-> add (make_product_context(d)); // The product needs a product definition formation to describe // the version with an id and description // stp_product_definition_formation* pdf = pnewIn(d) stp_product_definition_formation; pdf-> of_product(pr); pdf-> id ("1.0"); pdf-> description ("first version of our widget"); // The PDF needs a product definition. This describes a the // version from a particular point of view in the life cycle, so // most APs only have one per PDF, but some APs use several. // The frame of reference context information is boilerplate, // see context_utils.cxx for the specifics. // stp_product_definition* pd = pnewIn(d) stp_product_definition(); pd-> formation (pdf); pd-> id ("design"); pd-> description ("example product_definition"); pd-> frame_of_reference (make_pdef_context(d)); // Give the product a shape property. Product_definition_shape is // a subtype of property_definition used for shape properties. It // refers to the product through the product_definition. // stp_product_definition_shape * pds = pnewIn(d) stp_product_definition_shape; pds-> name (""); pds-> definition (pnewIn(d) stp_characterized_definition); pds-> definition ()-> _characterized_product_definition (pnewIn(d) stp_characterized_product_definition); pds-> definition ()-> _characterized_product_definition()-> _product_definition (pd); return pds; } // Create a shape rep with parameters and attach it to a product // definition shape. Give the shape rep a geometric context that uses // the length unit provided. // stp_representation * make_shape_rep_with_params( stp_product_definition_shape * pds, stp_named_unit * len_unit ) { if (!pds || !len_unit) return 0; RoseDesign * d = pds-> design(); // Add the feature orientation. It is an axis placement named // "orientation" in a special representation subtype. This is // also shared with the profiles and paths as their origin too. // stp_representation * rep = pnewIn(d) stp_shape_representation_with_parameters; rep-> name (""); rep-> context_of_items (make_common_context(len_unit)); // Attach the shape representation to the pds. stp_shape_definition_representation * sdr = pnewIn(d) stp_shape_definition_representation; sdr-> definition (pnewIn(d) stp_represented_definition); sdr-> definition ()-> _property_definition (pds); sdr-> used_representation (rep); return rep; } // Create a shape rep for the explicit representation of a feature and // attach it to a product definition shape. Give the shape rep a // geometric context that uses the length unit provided. // stp_representation * make_explicit_shape_rep( stp_product_definition_shape * pds, stp_named_unit * len_unit ) { if (!pds || !len_unit) return 0; RoseDesign * d = pds-> design(); stp_representation * rep = pnewIn(d) stp_shape_representation; rep-> name ("explicit feature shape"); rep-> context_of_items (make_common_context(len_unit)); // Attach the shape representation to the pds. stp_shape_definition_representation * sdr = pnewIn(d) stp_shape_definition_representation; sdr-> definition (pnewIn(d) stp_represented_definition); sdr-> definition ()-> _property_definition (pds); sdr-> used_representation (rep); return rep; } // Create and add a length measure rep item with a given value and // unit. The measure is created in the same design as the unit. // stp_measure_representation_item * make_length_measure( double len, stp_named_unit * len_unit ) { if (!len_unit) return 0; RoseDesign * d = len_unit-> design(); // Need a complex instance of measure rep item with the length // measure subtype for lengths. Similar subtypes are used for // plane angles, times, and ratios. // stp_measure_representation_item * mri = pnewIn(d) stp_length_measure_with_unit_and_measure_representation_item; stp_unit * u = pnewIn(d) stp_unit; u-> _named_unit(len_unit); stp_measure_value * mv = pnewIn (d) stp_measure_value; mv-> _length_measure (len); mri-> value_component(mv); mri-> unit_component(u); return mri; } // Makes a geometry context for use in all of the representations. // Save a shortcut to it for future use so that we only create one. // stp_representation_context * make_common_context( stp_named_unit * len_unit ) { const char * shortcut = "__CONSTANT GEMOMETRY CONTEXT"; RoseDesign * d = len_unit->design(); RoseObject * obj = d-> findObject (shortcut); if (obj) return ROSE_CAST (stp_representation_context, obj); stp_representation_context * ctx = make_geometry_context ( d, // location to create the context "ID1", // some name for the context 3, // number of dimensions, ie 3D len_unit, // length unit for geometry make_degree_unit (d), // angle unit for geometry make_steradian_unit (d) // solid angle unit ); d-> addName (shortcut, ctx); // save shortcut for future calls return ctx; } // All feature components (profiles and paths) are shape aspects that // point to an instance of a feature_component_definition in their // of_shape attribute. Only one of these needs to be in a file. // stp_product_definition_shape * make_feature_component_definition( RoseDesign * d ) { const char * shortcut = "__CONSTANT FEATURE COMPONENT DEFINITION"; if (!d) d = ROSE.design(); // Use shortcut to unit if we have already created one. The // shortcut is to the product definition shape rather than the // feature component definition because that is what everyone // points to. // RoseObject * obj = d-> findObject (shortcut); if (obj) return ROSE_CAST (stp_product_definition_shape, obj); stp_feature_component_definition * fcd = pnewIn (d) stp_feature_component_definition; // Give the product a shape property which is what the feature // components refer to. // stp_product_definition_shape * pds = pnewIn (d) stp_product_definition_shape; pds-> name (""); pds-> definition (pnewIn(d) stp_characterized_definition); pds-> definition ()-> _characterized_object (fcd); d-> addName (shortcut, pds); // save shortcut for future calls return pds; }