/* * Copyright (c) 1991-2024 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 "context_utils.h" #include "unit_utils.h" #include "findface.h" #include "tolerance.h" // The TOLERANCE sample program demonstrates how to create STEP // tolerances. int main(int /*argc*/, char** /*argv*/) { stplib_init(); // initialize STEP class library rose_p28_init(); // support xml read/write const char * input_name = "block_and_hole.stp"; const char * output_name = "block_with_tols.stp"; RoseDesign * design = ROSE.findDesign (input_name); if (!design) { printf ("ERROR: Could not read input file!\n"); exit(1); } // Regardless of whatever schema the original file used, we now // want to treat this as an AP214 file, since that has tolerances. // We could also use ap203e2 or ap242. // stplib_put_schema (design, stplib_schema_ap214); // Needed for the findface.h functions, gives more efficient // searching through the model. rose_compute_backptrs (design); // Get the faces of the block. The sample data has given them // special representation item names so we can find them easily, // but in practice a user will probably pick them using a viewer. // These return advanced_face entities, which is the customary // thing to add tolerances to. stp_advanced_face * top_face = find_face_by_name (design, "top face"); stp_advanced_face * bot_face = find_face_by_name (design, "bottom face"); stp_advanced_face * east_face = find_face_by_name (design, "east face"); stp_advanced_face * west_face = find_face_by_name (design, "west face"); stp_advanced_face * north_face = find_face_by_name (design, "north face"); stp_advanced_face * south_face = find_face_by_name (design, "south face"); stp_advanced_face * hole_face = find_face_by_name (design, "large hole"); // Find the product associated with the face. Datums and the // callouts used by tolerances are shape aspects that must be // hooked to the product via the product_definition_shape. // stp_product_definition_shape * pds = find_pdef_shape_for_repitem (top_face); // Use the same geometry context for our datums and tols. stp_representation_context * ctx = find_rep_context_for_repitem (top_face); // Unit that we will use for our tolerance values stp_named_unit * mm = make_mm_unit (design); // Set up the datums on the sides of the part. stp_datum * dat_a = make_datum ("A", pds, ctx, east_face); stp_datum * dat_b = make_datum ("B", pds, ctx, south_face); stp_datum * dat_c = make_datum ("C", pds, ctx, bot_face); // Call out some faces using shape aspects that we will apply // tolerances to // stp_shape_aspect * top_callout = make_callout (pds, ctx, top_face); stp_shape_aspect * bot_callout = make_callout (pds, ctx, bot_face); stp_shape_aspect * east_callout = make_callout (pds, ctx, east_face); stp_shape_aspect * west_callout = make_callout (pds, ctx, west_face); stp_shape_aspect * north_callout = make_callout (pds, ctx, north_face); stp_shape_aspect * south_callout = make_callout (pds, ctx, south_face); stp_shape_aspect * hole_callout = make_callout (pds, ctx, hole_face); // MAKE A flatness tolerance, no datums needed make_flatness_tol (top_callout, 0.1, mm); // MAKE A position tolerance and apply all datums stp_geometric_tolerance_with_datum_reference * pos = make_position_tol (top_callout, 0.1, mm); add_datum (pos, dat_a); add_datum (pos, dat_b); add_datum (pos, dat_c); // MAKE A perpendicularity tolerance for one of the side faces // based on the bottom. stp_geometric_tolerance_with_datum_reference * perp = make_perpendicularity_tol (west_callout, 0.1, mm); add_datum (perp, dat_c); // Apply some dimensions to the model make_linear_dimension (east_callout, west_callout, 80, mm, +0.1, -0.2); make_linear_dimension (north_callout, south_callout, 60, mm, +0.1, -0.2); make_linear_dimension (top_callout, bot_callout, 20, mm, +0.1, -0.2); // Apply a diameter dimension to the model make_diameter_dimension (hole_callout, 18, mm, +0.1, -0.2); design-> saveAs (output_name); return 0; } //============================================================ // DIMENSIONS -- These apply a location dimensions to a given pair of // callouts, or a size dimension to a single callout. // stp_dimensional_location * make_linear_dimension ( stp_shape_aspect * start_callout, stp_shape_aspect * end_callout, double val, stp_named_unit * u, double plus_tol, double minus_tol ) { RoseDesign * d = u-> design(); // if not a directed dimension (i.e. it can be measured either // way) then use the supertype stp_dimensional_location. stp_directed_dimensional_location * dim = pnewIn(d) stp_directed_dimensional_location; dim-> name("linear distance"); dim-> description(""); dim-> relating_shape_aspect (start_callout); dim-> related_shape_aspect (end_callout); stp_dimensional_characteristic_representation * dcr = pnewIn(d) stp_dimensional_characteristic_representation; dcr-> dimension (pnewIn(d) stp_dimensional_characteristic); dcr-> dimension()-> _dimensional_location(dim); stp_measure_representation_item * it = make_length_repitem (val, u); dcr-> representation (pnewIn(d) stp_shape_dimension_representation); dcr-> representation()-> name(""); dcr-> representation()-> items()-> add(it); dcr-> representation()-> context_of_items (make_simple_rep_context(d)); // Add in the plus/minus values stp_plus_minus_tolerance * pm = pnewIn(d) stp_plus_minus_tolerance; pm-> toleranced_dimension (pnewIn(d) stp_dimensional_characteristic); pm-> toleranced_dimension()-> _dimensional_location(dim); pm-> range (pnewIn(d) stp_tolerance_method_definition); pm-> range()-> _tolerance_value (pnewIn(d) stp_tolerance_value); pm-> range()-> _tolerance_value()-> upper_bound ( make_length_mwu (plus_tol, u) ); pm-> range()-> _tolerance_value()-> lower_bound ( make_length_mwu (minus_tol, u) ); return dim; } stp_dimensional_size * make_diameter_dimension ( stp_shape_aspect * callout, double val, stp_named_unit * u, double plus_tol, double minus_tol ) { RoseDesign * d = u-> design(); // if not a directed dimension (i.e. it can be measured either // way) then use the supertype stp_dimensional_location. stp_dimensional_size * dim = pnewIn(d) stp_dimensional_size; dim-> name("diameter"); dim-> applies_to (callout); stp_dimensional_characteristic_representation * dcr = pnewIn(d) stp_dimensional_characteristic_representation; dcr-> dimension (pnewIn(d) stp_dimensional_characteristic); dcr-> dimension()-> _dimensional_size(dim); stp_measure_representation_item * it = make_length_repitem (val, u); dcr-> representation (pnewIn(d) stp_shape_dimension_representation); dcr-> representation()-> items()-> add(it); dcr-> representation()-> context_of_items (make_simple_rep_context(d)); // Add in the plus/minus values stp_plus_minus_tolerance * pm = pnewIn(d) stp_plus_minus_tolerance; pm-> toleranced_dimension (pnewIn(d) stp_dimensional_characteristic); pm-> toleranced_dimension()-> _dimensional_size(dim); pm-> range (pnewIn(d) stp_tolerance_method_definition); pm-> range()-> _tolerance_value (pnewIn(d) stp_tolerance_value); pm-> range()-> _tolerance_value()-> upper_bound ( make_length_mwu (plus_tol, u) ); pm-> range()-> _tolerance_value()-> lower_bound ( make_length_mwu (minus_tol, u) ); return dim; } //============================================================ // TOLERANCE -- These apply tolerances to a given callout. You may // still need to add datum references. // stp_geometric_tolerance * make_flatness_tol ( stp_shape_aspect * callout, double val, stp_named_unit * u ) { RoseDesign * d = u-> design(); stp_geometric_tolerance * tol = pnewIn(d) stp_flatness_tolerance; tol-> name(""); tol-> description(""); tol-> magnitude (make_length_mwu (val, u)); // AP242 adds a select so it can refer to more than shape aspects tol-> toleranced_shape_aspect(pnewIn(d) stp_geometric_tolerance_target); tol-> toleranced_shape_aspect()->_shape_aspect(callout); return tol; } stp_geometric_tolerance_with_datum_reference * make_position_tol ( stp_shape_aspect * callout, double val, stp_named_unit * u ) { RoseDesign * d = u-> design(); // This needs a complex instance to use datums stp_geometric_tolerance_with_datum_reference * tol = pnewIn(d) stp_geometric_tolerance_with_datum_reference_and_position_tolerance; tol-> name(""); tol-> description(""); tol-> magnitude (make_length_mwu (val, u)); // AP242 adds a select so it can refer to more than shape aspects tol-> toleranced_shape_aspect(pnewIn(d) stp_geometric_tolerance_target); tol-> toleranced_shape_aspect()->_shape_aspect(callout); return tol; } stp_geometric_tolerance_with_datum_reference * make_perpendicularity_tol ( stp_shape_aspect * callout, double val, stp_named_unit * u ) { RoseDesign * d = u-> design(); // This needs a complex instance to use datums stp_geometric_tolerance_with_datum_reference * tol = pnewIn(d) stp_perpendicularity_tolerance; tol-> name(""); tol-> description(""); tol-> magnitude (make_length_mwu (val, u)); // AP242 adds a select so it can refer to more than shape aspects tol-> toleranced_shape_aspect(pnewIn(d) stp_geometric_tolerance_target); tol-> toleranced_shape_aspect()->_shape_aspect(callout); return tol; } //============================================================ // DATUMS -- A datum is attached to a specific face using a related // datum feature. The function below creates both. // stp_datum * make_datum ( const char * datum_name, stp_product_definition_shape * pds, stp_representation_context * ctx, stp_representation_item * face ) { RoseDesign * d = face-> design(); // make the base datum object stp_datum * dat = pnewIn(d) stp_datum; dat-> name(""); dat-> description(""); dat-> product_definitional (ROSE_FALSE); dat-> of_shape (pds); dat-> identification(datum_name); // make a datum feature to associate the geometry stp_datum_feature * feat = pnewIn(d) stp_datum_feature; feat-> name(""); feat-> description(""); feat-> product_definitional (ROSE_FALSE); feat-> of_shape (pds); // associate the face with the feature stp_shape_representation * rep = pnewIn(d) stp_shape_representation; rep-> name(""); rep-> context_of_items(ctx); rep-> items()-> add(face); stp_property_definition * prop = pnewIn(d) stp_property_definition; prop-> name(""); prop-> definition (pnewIn(d) stp_characterized_definition); rose_put_nested_object (prop-> definition(), feat); stp_shape_definition_representation * sdr = pnewIn(d) stp_shape_definition_representation; sdr-> used_representation (rep); sdr-> definition (pnewIn(d) stp_represented_definition); sdr-> definition()-> _property_definition (prop); // Finally, associate the feature with the datum stp_shape_aspect_relationship * rel = pnewIn(d) stp_shape_aspect_relationship; rel-> name(""); rel-> description(""); rel-> relating_shape_aspect(feat); rel-> related_shape_aspect(dat); return dat; } void add_datum ( stp_geometric_tolerance_with_datum_reference * tol, stp_datum * dat ) { RoseDesign * d = tol-> design(); stp_datum_reference * ref = pnewIn(d) stp_datum_reference; ref-> referenced_datum (dat); // AP242 adds a select so it can refer to a system stp_datum_system_or_reference * sysref = pnewIn(d) stp_datum_system_or_reference; sysref-> _datum_reference (ref); tol-> datum_system()-> add (sysref); ref-> precedence (tol-> datum_system()-> size()); } //============================================================ // CALLOUT SHAPE ASPECTS -- Tolerances are usually applied to // a shape aspect which points to some elements of the product // geometry. // void add_callout_face ( stp_shape_definition_representation * callout_sdr, stp_representation_item * face ) { if (!callout_sdr || !callout_sdr-> used_representation()) return; callout_sdr-> used_representation()-> items()-> add (face); } stp_shape_aspect * find_callout_aspect ( stp_shape_definition_representation * sdr ) { if (!sdr) return 0; stp_property_definition * prop = ROSE_CAST(stp_property_definition, rose_get_nested_object(sdr->definition()) ); if (prop) { return ROSE_CAST(stp_shape_aspect, rose_get_nested_object(prop->definition()) ); } return 0; } stp_shape_definition_representation * make_empty_callout ( stp_product_definition_shape * pds, stp_representation_context * ctx ) { RoseDesign * d = pds-> design(); // make a shape aspect to associate the geometry stp_shape_aspect * sa = pnewIn(d) stp_shape_aspect; sa-> name(""); sa-> description(""); sa-> product_definitional (ROSE_FALSE); sa-> of_shape (pds); // make an empty shape rep to hold faces stp_shape_representation * rep = pnewIn(d) stp_shape_representation; rep-> name(""); rep-> context_of_items(ctx); stp_property_definition * prop = pnewIn(d) stp_property_definition; prop-> name(""); prop-> definition (pnewIn(d) stp_characterized_definition); rose_put_nested_object (prop-> definition(), sa); stp_shape_definition_representation * sdr = pnewIn(d) stp_shape_definition_representation; sdr-> used_representation (rep); sdr-> definition (pnewIn(d) stp_represented_definition); sdr-> definition()-> _property_definition (prop); return sdr; } stp_shape_aspect * make_callout ( stp_product_definition_shape * pds, stp_representation_context * ctx, stp_representation_item * face ) { // Make the callout and add the face. This uses two functions so // that you can add multiple faces if desired. Return the callout // shape aspect because that is what the tolerances point to. // stp_shape_definition_representation * sdr = make_empty_callout (pds, ctx); add_callout_face (sdr, face); return find_callout_aspect (sdr); } //============================================================ // MEASURE VALUES -- Depending on whether these are used in a // representation, these measure_with_unit objects may also be a // measure_representation_item. // stp_length_measure_with_unit * make_length_mwu ( double val, stp_named_unit * u ) { RoseDesign * d = u-> design(); // Use a special subtype for length measures stp_length_measure_with_unit * mwu = pnewIn(d) stp_length_measure_with_unit; mwu-> value_component (pnewIn(d) stp_measure_value); mwu-> value_component()-> _length_measure(val); mwu-> unit_component (pnewIn(d) stp_unit); mwu-> unit_component()-> _named_unit(u); return mwu; } stp_measure_representation_item * make_length_repitem ( double val, stp_named_unit * u ) { RoseDesign * d = u-> design(); // Use a special complex instance for length measures stp_measure_representation_item * mwu = pnewIn(d) stp_length_measure_with_unit_and_measure_representation_item; mwu-> name(""); mwu-> value_component (pnewIn(d) stp_measure_value); mwu-> value_component()-> _length_measure(val); mwu-> unit_component (pnewIn(d) stp_unit); mwu-> unit_component()-> _named_unit(u); return mwu; } stp_representation_context * make_simple_rep_context( RoseDesign * design ) { RoseCursor objs; RoseObject * obj; /* The data set should only contain one plain representation * context. There may be instances of the subtypes, but only * one of these. */ objs.traverse (design); objs.exact (ROSE_DOMAIN(stp_representation_context)); if ((obj = objs.next()) != 0) { return ROSE_CAST(stp_representation_context,obj); } /* should the make get or create? */ stp_representation_context * rc = pnewIn(design) stp_representation_context; rc-> context_identifier (""); rc-> context_type ("units not necessary"); return rc; }