From 0eef2adf2ec33dd0055b2dc00dc023c5496a41b3 Mon Sep 17 00:00:00 2001 From: jfa Date: Tue, 27 Dec 2022 14:21:51 +0300 Subject: [PATCH] [bos #32540] [EDF] Shaper constrains suggestions - Connection with AI Inference Engine --- src/SAMConverter/SAMConverter.py | 5 +- .../SAMConverter_SuggestConstraintsFeature.py | 91 +++++++++-- src/SAMConverter/Test/CMakeLists.txt | 1 + .../Test/TestSAMConverter_scenario1.py | 43 +++++ .../Test/TestSAMConverter_scenario2.py | 43 +++++ .../Test/data/ecrou_sam_scenario1.py | 66 ++++++++ src/SAMConverter/Test/data/ecrou_scenario1.py | 78 +++++++++ .../Test/data/plaque_trouee_sam_sc2.py | 51 ++++++ .../Test/data/plaque_trouee_shaper_sc2.py | 150 ++++++++++++++++++ .../data/predict_engine_mock_scenario1.py | 43 +++++ .../data/predict_engine_mock_scenario2.py | 43 +++++ src/SAMConverter/Test/tests.set | 2 + src/SketchPlugin/SketchPlugin_Plugin.cpp | 2 + 13 files changed, 603 insertions(+), 15 deletions(-) create mode 100644 src/SAMConverter/Test/TestSAMConverter_scenario1.py create mode 100644 src/SAMConverter/Test/TestSAMConverter_scenario2.py create mode 100644 src/SAMConverter/Test/data/ecrou_sam_scenario1.py create mode 100644 src/SAMConverter/Test/data/ecrou_scenario1.py create mode 100644 src/SAMConverter/Test/data/plaque_trouee_sam_sc2.py create mode 100644 src/SAMConverter/Test/data/plaque_trouee_shaper_sc2.py create mode 100644 src/SAMConverter/Test/data/predict_engine_mock_scenario1.py create mode 100644 src/SAMConverter/Test/data/predict_engine_mock_scenario2.py diff --git a/src/SAMConverter/SAMConverter.py b/src/SAMConverter/SAMConverter.py index 7cd95b94b..b34469629 100644 --- a/src/SAMConverter/SAMConverter.py +++ b/src/SAMConverter/SAMConverter.py @@ -23,6 +23,8 @@ import ModelAPI from SAMConverter_SuggestConstraintsFeature import SuggestConstraintsFeature +from SAMConverter_SuggestConstraintsFeature import getPathToSketchConstraintsFinder +from SAMConverter_SuggestConstraintsFeature import getSketchConstraintsFinder ## @ingroup Plugins # The main class for management the construction features as plugin. @@ -41,8 +43,7 @@ class SAMConverter(ModelAPI.ModelAPI_Plugin): print("SAMConverter: No such feature %s" % theFeatureID) ## The plugin created on module importing (from c++) -isSHAPER_SUGGESTION_GENERATOR = True -#TODO +isSHAPER_SUGGESTION_GENERATOR = getPathToSketchConstraintsFinder() if isSHAPER_SUGGESTION_GENERATOR: plugin = SAMConverter() ## Main session of the application diff --git a/src/SAMConverter/SAMConverter_SuggestConstraintsFeature.py b/src/SAMConverter/SAMConverter_SuggestConstraintsFeature.py index 5020a8a19..75d6f4129 100644 --- a/src/SAMConverter/SAMConverter_SuggestConstraintsFeature.py +++ b/src/SAMConverter/SAMConverter_SuggestConstraintsFeature.py @@ -33,6 +33,52 @@ import salome from salome.shaper import model import os +import sys +import pathlib +import importlib.util + +## Method to get path to AI Inference Engine +# \return None if the path is not found +def getPathToSketchConstraintsFinder(): + ai_engine_path = os.environ.get('SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI') + if not ai_engine_path: + print('SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI variable is not set') + return None + + print(ai_engine_path) + if not os.path.isfile(ai_engine_path): + print('{} is not a file'.format(ai_engine_path)) + return None + + file_extension = pathlib.Path(ai_engine_path).suffix + if file_extension == '.py' or file_extension == '.pyc': + return ai_engine_path + else: + print('{} is not a python file'.format(ai_engine_path)) + pass + + return None + +## Method to get AI Inference Engine class +# \return None if it is not found +def getSketchConstraintsFinder(): + ai_engine_path = getPathToSketchConstraintsFinder() + if not ai_engine_path: + return + + p = pathlib.Path(ai_engine_path) + ai_engine_name = p.stem + ai_spec = importlib.util.spec_from_file_location(ai_engine_name, ai_engine_path) + ai_engine = importlib.util.module_from_spec(ai_spec) + ai_spec.loader.exec_module(ai_engine) + + if not hasattr(ai_engine, 'AIEngine'): + print('There is no AIEngine in {}'.format(ai_engine_path)) + return + + ai_class_inst = getattr(ai_engine, 'AIEngine')() + return ai_class_inst + ## @ingroup Plugins # Feature to suggest constraints using a Machine Learning model @@ -56,8 +102,6 @@ class SuggestConstraintsFeature(ModelAPI.ModelAPI_Feature): ## False: Otherwise. def isAction(self): return False - #TODO - #return True def isMacro(self): """ @@ -92,7 +136,9 @@ class SuggestConstraintsFeature(ModelAPI.ModelAPI_Feature): 'SketchLine', # Next entities not compability with SAM, but it's avaliable elements 'SketchProjection', - 'SketchIntersection'] + 'SketchIntersection', + 'SketchMultiRotation', + 'SketchMultiTranslation'] nonConvertablePrimitive = [] nonConvertableConstraint = [] @@ -117,9 +163,9 @@ class SuggestConstraintsFeature(ModelAPI.ModelAPI_Feature): ## Check that all primitives and constraints is compability with SAM nonConvertablePrimitive, nonConvertableConstraint = self.isConvertedSketch() if len(nonConvertablePrimitive) > 0 or len(nonConvertableConstraint) > 0 : - logger.debug("SuggestConstraints", f'Primitives and constraints are incompatible with the SAM format. The sequence therefore cannot be translated.') + logger.debug("SuggestConstraints %s", f'Primitives and constraints are incompatible with the SAM format. The sequence therefore cannot be translated.') if len(nonConvertablePrimitive) > 0: - logger.debug("SuggestConstraints", f'List of primitives not compatible with SAM: {nonConvertablePrimitive}') + logger.debug("SuggestConstraints %s", f'List of primitives not compatible with SAM: {nonConvertablePrimitive}') if len(nonConvertableConstraint) > 0: logger.debug(f'List of constraints not compatible with SAM: {nonConvertableConstraint}') ### For users @@ -130,16 +176,23 @@ class SuggestConstraintsFeature(ModelAPI.ModelAPI_Feature): EventsAPI.Events_InfoMessage("SuggestConstraints", f'The primitives: {nonConvertablePrimitive} are not currently taken into account by the model.', self).send() else: EventsAPI.Events_InfoMessage("SuggestConstraints", f'The primitives: {nonConvertablePrimitive} and constraints {nonConvertableConstraint} are not currently taken into account by the model.', self).send() - return + return None - exchange_elements = convert_sketch(self.Sketch) + exchange_sketch = convert_sketch(self.Sketch) print("SuggestConstraintsFeature: convertToSAM") - pass + return exchange_sketch - ## Exports all shapes and groups into the GEOM module. + ## TODO: Apply new constraints def execute(self): - ## Find skecth + #ApplyNewConstraints() + # TMP + self.PredictConstraints() + + + ## Convert current sketch to SAM format and pass it to AI Inference Engine + def PredictConstraints(self): + # 1. Find skecth aSession = ModelAPI.ModelAPI_Session.get() aPartSet = aSession.moduleDocument() self.Part = model.activeDocument() @@ -148,8 +201,20 @@ class SuggestConstraintsFeature(ModelAPI.ModelAPI_Feature): self.Sketch = SketchAPI_Sketch(feat) break + # 2. Convert Sketch to SAM format print("SuggestConstraintsFeature: execute") - self.convertToSAM() - # TODO: Lot3 and Lot4 + exchange_sketch = self.convertToSAM() + # TODO: obtain also mapping - pass + # 3. Pass SAM model to AI Inference Engine + # and get the list of predicted constraints + ai_class_inst = getSketchConstraintsFinder() + if not ai_class_inst: + return + + predicted_list = ai_class_inst.Predict(exchange_sketch) + print(predicted_list) + + # 4. TODO: Show the list of proposed constraints to the user + + return predicted_list diff --git a/src/SAMConverter/Test/CMakeLists.txt b/src/SAMConverter/Test/CMakeLists.txt index 6860ac008..e8a3d70f5 100644 --- a/src/SAMConverter/Test/CMakeLists.txt +++ b/src/SAMConverter/Test/CMakeLists.txt @@ -43,3 +43,4 @@ INSTALL(FILES CTestTestfileInstall.cmake RENAME CTestTestfile.cmake) INSTALL(FILES tests.set DESTINATION ${TEST_INSTALL_DIRECTORY}) +INSTALL(DIRECTORY data DESTINATION ${TEST_INSTALL_DIRECTORY}) diff --git a/src/SAMConverter/Test/TestSAMConverter_scenario1.py b/src/SAMConverter/Test/TestSAMConverter_scenario1.py new file mode 100644 index 000000000..c70131ef8 --- /dev/null +++ b/src/SAMConverter/Test/TestSAMConverter_scenario1.py @@ -0,0 +1,43 @@ +import os +import sys +sys.path.append('data/') + +import SAMConverter + +if __name__ == "__main__" : + from ecrou_sam_scenario1 import ecrou_sam + from ecrou_scenario1 import Sketch_1 + + # If SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI is set, use it (suppose it is true AI Engine) + # Otherwise, set it to the special mock for scenario1 + isAIEngineEnvSet = True + ai_engine_path = os.environ.get('SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI') + if not ai_engine_path or ai_engine_path == "": + isAIEngineEnvSet = False + this_script_path = os.path.dirname(os.path.realpath(sys.argv[0] or 'something')) + os.environ['SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI'] = os.path.join(this_script_path, 'data', 'predict_engine_mock_scenario1.py') + pass + + ai_engine = SAMConverter.getSketchConstraintsFinder() + assert(ai_engine) + + # 1. Predict constraints on SAM model + pred = ai_engine.Predict(ecrou_sam) + for key,value in pred.items() : + print(f' {key} : {value}') + pass + + # 2. Predict constraints on Shaper model (convert to SAM beforehand) + aFeature = SAMConverter.SuggestConstraintsFeature() + pred_shaper = aFeature.PredictConstraints() + for key,value in pred_shaper.items() : + print(f' {key} : {value}') + pass + + if not isAIEngineEnvSet: + os.environ.pop('SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI', None) + pass + + # for i, x in enumerate(ecrou_sam.sequence): + # if 'Line' in str(x) : + # print(i, x) diff --git a/src/SAMConverter/Test/TestSAMConverter_scenario2.py b/src/SAMConverter/Test/TestSAMConverter_scenario2.py new file mode 100644 index 000000000..2e8d3feff --- /dev/null +++ b/src/SAMConverter/Test/TestSAMConverter_scenario2.py @@ -0,0 +1,43 @@ +import os +import sys +sys.path.append('data/') + +import SAMConverter + +if __name__ == "__main__" : + from plaque_trouee_sam_sc2 import plaque_trouee_sam + from plaque_trouee_shaper_sc2 import Sketch_1 + + # If SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI is set, use it (suppose it is true AI Engine) + # Otherwise, set it to the special mock for scenario1 + isAIEngineEnvSet = True + ai_engine_path = os.environ.get('SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI') + if not ai_engine_path or ai_engine_path == "": + isAIEngineEnvSet = False + this_script_path = os.path.dirname(os.path.realpath(sys.argv[0] or 'something')) + os.environ['SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI'] = os.path.join(this_script_path, 'data', 'predict_engine_mock_scenario2.py') + pass + + ai_engine = SAMConverter.getSketchConstraintsFinder() + assert(ai_engine) + + # 1. Predict constraints on SAM model + pred = ai_engine.Predict(plaque_trouee_sam) + for key,value in pred.items() : + print(f' {key} : {value}') + pass + + # 2. Predict constraints on Shaper model (convert to SAM beforehand) + aFeature = SAMConverter.SuggestConstraintsFeature() + pred_shaper = aFeature.PredictConstraints() + for key,value in pred_shaper.items() : + print(f' {key} : {value}') + pass + + if not isAIEngineEnvSet: + os.environ.pop('SHAPER_SKETCH_CONSTRAINT_SUGGESTION_AI', None) + pass + + # for i, x in enumerate(ecrou_sam.sequence): + # if 'Line' in str(x) : + # print(i, x) diff --git a/src/SAMConverter/Test/data/ecrou_sam_scenario1.py b/src/SAMConverter/Test/data/ecrou_sam_scenario1.py new file mode 100644 index 000000000..35c3e2fa3 --- /dev/null +++ b/src/SAMConverter/Test/data/ecrou_sam_scenario1.py @@ -0,0 +1,66 @@ +from sam.sketch import Sketch +from sam.catalog_primitive import Point, Circle, Line +from sam.catalog_constraint import * + +nb = 6 +k = 13 +ecrou_sam = Sketch() + +# Add Origin Point +point_origin = Point(status_construction=True, point=[0., 0.]) +ecrou_sam.add(point_origin) + +# Add Circle +circle = Circle(status_construction=False, center=[0., 0.], radius=3.9) +ecrou_sam.add(circle) + +# Add Constraint radius + coincident +ecrou_sam.add(Coincident(references = [circle.center, point_origin])) + +# Add Line + +line_1 = Line(status_construction=True, pnt1 = [3.9,0.], pnt2= [7.505553499465127, 0.]) +ecrou_sam.add(line_1) +ecrou_sam.add(Coincident(references = [circle, line_1.pnt1])) +ecrou_sam.add(Horizontal(references = [line_1])) + +# Traduction de SketchProjection ??, +# line_2 = ??? + + +# Add line 3 +line_3 = Line(status_construction=False, pnt1 = [7.505553499465127, 0], pnt2= [3.752776749732566, 6.499999999999992]) +ecrou_sam.add(line_3) +ecrou_sam.add(Coincident(references = [line_1.pnt2, line_3.pnt1])) +ecrou_sam.add(Distance( references = [point_origin, line_3], distance_min=k/2)) + +# Add line 4 +line_4 = Line(status_construction=True, pnt1 = [3.752776749732566, 6.499999999999992], pnt2= [1.950000000000005, 3.377499074759307]) +ecrou_sam.add(line_4) +ecrou_sam.add(Coincident(references = [line_3.pnt2, line_4.pnt1])) +ecrou_sam.add(Coincident(references = [line_4.pnt2, circle])) +ecrou_sam.add(Equal(references = [line_1, line_4])) + + +# Manque la rotation multiple -> add multiple line +line_5 = Line(status_construction=False, pnt1 = [3.7527767497325644, 6.499999999999993], pnt2= [-3.7527767497325604, 6.499999999999996]) +ecrou_sam.add(line_5) +ecrou_sam.add(Coincident(references = [line_4.pnt2, line_5.pnt1])) + +line_6 = Line(status_construction=False, pnt1 = [-3.752776749732562, 6.499999999999995], pnt2= [-7.505553499465128, 4.884981308350689e-15]) +ecrou_sam.add(line_6) +ecrou_sam.add(Coincident(references = [line_5.pnt2, line_6.pnt1])) + +line_7 = Line(status_construction=False, pnt1 = [-7.505553499465128, 3.1086244689504383e-15], pnt2= [-3.7527767497325693, -6.499999999999991]) +ecrou_sam.add(line_7) +ecrou_sam.add(Coincident(references = [line_6.pnt2, line_7.pnt1])) + +line_8 = Line(status_construction=False, pnt1 = [-3.7527767497325675, -6.499999999999992], pnt2= [3.7527767497325577, -6.499999999999998]) +ecrou_sam.add(line_8) +ecrou_sam.add(Coincident(references = [line_7.pnt2, line_8.pnt1])) + +line_9 = Line(status_construction=False, pnt1 = [3.7527767497325595, -6.4999999999999964], pnt2= [7.505553499465128, -8.43769498715119e-15]) +ecrou_sam.add(line_9) +ecrou_sam.add(Coincident(references = [line_8.pnt2, line_9.pnt1])) + +ecrou_sam.add(Coincident(references = [line_9.pnt2, line_3.pnt1])) diff --git a/src/SAMConverter/Test/data/ecrou_scenario1.py b/src/SAMConverter/Test/data/ecrou_scenario1.py new file mode 100644 index 000000000..9689055d1 --- /dev/null +++ b/src/SAMConverter/Test/data/ecrou_scenario1.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""L'écrou - CAO avec SHAPER + +Copyright 2020 EDF +Gérald NICOLAS ++33.1.78.19.43.52 +""" +from salome.shaper import model +from SketchAPI import * +__revision__ = "V03.02" + +import salome + +salome.salome_init() + +### +# SHAPER component +### + + +model.begin() +partSet = model.moduleDocument() + +# Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +model.addParameter(Part_1_doc, "nb", "6") +model.addParameter(Part_1_doc, "k", "13") + +# Create Sketch +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) + +# Create SketchProjection +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() + +# Create SketchCircle +SketchCircle_1 = Sketch_1.addCircle(0, 0, 3.9) +Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center()) + +# Create SketchLine +SketchLine_1 = Sketch_1.addLine(3.9, 0, 7.505553499465127, 0) +SketchLine_1.setAuxiliary(True) +Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchCircle_1.results()[1]) +Sketch_1.setHorizontal(SketchLine_1.result()) + +# Create SketchProjection +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False) +SketchLine_2 = SketchProjection_2.createdFeature() +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.result()) + +# Create SketchLine +SketchLine_3 = Sketch_1.addLine(7.505553499465127, 0, 3.752776749732566, 6.499999999999992) +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_3.startPoint()) +Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.result(), "k/2", True) + +# Create SketchLine +SketchLine_4 = Sketch_1.addLine(3.752776749732566, 6.499999999999992, 1.950000000000005, 3.377499074759307) +SketchLine_4.setAuxiliary(True) +Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchCircle_1.results()[1]) +Sketch_1.setEqual(SketchLine_1.result(), SketchLine_4.result()) + + + +# Create SketchMultiRotation +SketchMultiRotation_1 = Sketch_1.addRotation([SketchLine_3.result()], SketchAPI_Point(SketchPoint_1).coordinates(), 360, "nb", True) +[SketchLine_5, SketchLine_6, SketchLine_7, SketchLine_8, SketchLine_9] = SketchMultiRotation_1.rotated() + +model.do() + + +model.end() + + +if salome.sg.hasDesktop(): + salome.sg.updateObjBrowser() diff --git a/src/SAMConverter/Test/data/plaque_trouee_sam_sc2.py b/src/SAMConverter/Test/data/plaque_trouee_sam_sc2.py new file mode 100644 index 000000000..1f8a5656d --- /dev/null +++ b/src/SAMConverter/Test/data/plaque_trouee_sam_sc2.py @@ -0,0 +1,51 @@ +from sam.sketch import Sketch +from sam.catalog_primitive import Arc, Line +from sam.catalog_constraint import * + +H = 150 +L = 100 +a = 10 + +plaque_trouee_sam = Sketch() + + +line_1 = Line(status_construction=False, pnt1 = [0.0, 10.0], pnt2= [0.0, 150.0]) +plaque_trouee_sam.add(line_1) + +line_2 = Line(status_construction=False, pnt1 = [0.0, 150.0], pnt2= [100.0, 150.0]) +plaque_trouee_sam.add(line_2) +plaque_trouee_sam.add(Coincident(references = [line_1.pnt2, line_2.pnt1])) + +line_3 = Line(status_construction=False, pnt1 = [100.0, 150.0], pnt2= [100.0, 0.0]) +plaque_trouee_sam.add(line_3) +plaque_trouee_sam.add(Coincident(references = [line_2.pnt2, line_3.pnt1])) + +line_4 = Line(status_construction=False, pnt1 = [100.0, 0.0], pnt2= [10.0, 0.0]) +plaque_trouee_sam.add(line_4) +# plaque_trouee_sam.add(Coincident(references = [line_3.pnt2, line_4.pnt1])) + +line_5 = Line(status_construction=False, pnt1 = [0.0, 0.0], pnt2= [0.0, 100.0]) +plaque_trouee_sam.add(line_5) + +line_6 = Line(status_construction=False, pnt1 = [0.0, 0.0], pnt2= [100.0, 0.0]) +plaque_trouee_sam.add(line_6) + +arc= Arc(status_construction=False, center=[0., 0.], radius=10.0, angles=[0., 90.]) +plaque_trouee_sam.add(arc) + +plaque_trouee_sam.add(Coincident(references = [line_4.pnt1, line_6])) +# plaque_trouee_sam.add(Vertical(references = [line_1])) +# plaque_trouee_sam.add(Vertical(references = [line_3])) +# plaque_trouee_sam.add(Horizontal(references = [line_4])) +# plaque_trouee_sam.add(Horizontal(references = [line_2])) + +plaque_trouee_sam.add(Coincident(references = [line_1.pnt1, line_5])) +plaque_trouee_sam.add(Coincident(references = [line_4.pnt1, line_6])) + +# plaque_trouee_sam.add(Length(references = [line_3], length = L)) +# plaque_trouee_sam.add(Length(references = [line_2], length = H)) +plaque_trouee_sam.add(Coincident(references = [arc.center, line_6])) +plaque_trouee_sam.add(Coincident(references = [arc, line_1.pnt1])) +plaque_trouee_sam.add(Coincident(references = [arc, line_4.pnt2])) +plaque_trouee_sam.add(Radius(references = [arc], radius = a)) + diff --git a/src/SAMConverter/Test/data/plaque_trouee_shaper_sc2.py b/src/SAMConverter/Test/data/plaque_trouee_shaper_sc2.py new file mode 100644 index 000000000..96167ca06 --- /dev/null +++ b/src/SAMConverter/Test/data/plaque_trouee_shaper_sc2.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""1/4 de plaque trouée ; CAO avec SHAPER + +Copyright 2020 EDF +Gérald NICOLAS ++33.1.78.19.43.52 +""" +__revision__ = "V04.01" + + +import os +import sys +import salome + +salome.salome_init() + +### +### SHAPER component +### + +from SketchAPI import * + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +model.addParameter(Part_1_doc, "H", '150') +model.addParameter(Part_1_doc, "L", '100') +model.addParameter(Part_1_doc, "a", '10') +model.addParameter(Part_1_doc, "DZ", '30.') + +### Create Sketch +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) + +### Create SketchLine +SketchLine_1 = Sketch_1.addLine(0, 10, 0, 150) + +### Create SketchLine +SketchLine_2 = Sketch_1.addLine(0, 150, 100, 150) +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) + +### Create SketchLine +SketchLine_3 = Sketch_1.addLine(100, 150, 100, 0) +Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) + +### Create SketchLine +SketchLine_4 = Sketch_1.addLine(100, 0, 10, 0) +# Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +# Sketch_1.setVertical(SketchLine_1.result()) +# Sketch_1.setVertical(SketchLine_3.result()) +# Sketch_1.setHorizontal(SketchLine_4.result()) +# Sketch_1.setHorizontal(SketchLine_2.result()) + +### Create SketchProjection +SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False) +SketchLine_5 = SketchProjection_1.createdFeature() +Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_5.result()) + +### Create SketchProjection +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False) +SketchLine_6 = SketchProjection_2.createdFeature() +Sketch_1.setCoincident(SketchLine_4.startPoint(), SketchLine_6.result()) +# Sketch_1.setLength(SketchLine_3.result(), "H") +# Sketch_1.setLength(SketchLine_2.result(), "L") + +### Create SketchArc +SketchArc_1 = Sketch_1.addArc(0, 0, 0, 10, 10, 0, True) +Sketch_1.setCoincident(SketchArc_1.center(), SketchAPI_Line(SketchLine_6).startPoint()) +Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_1.startPoint()) +Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_4.endPoint()) +Sketch_1.setRadius(SketchArc_1.results()[1], "a") +model.do() + +### Create Face +Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2r-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")]) +Face_1.result().setName("Plaque") + +### Create Extrusion +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Plaque")], model.selection(), "DZ", 0) + +### Create Group +Group_1 = model.addGroup(Part_1_doc, "FACE", [model.selection("FACE", "Plaque/From_Face")]) +Group_1.setName("face_Zm") +Group_1.result().setName("face_Zm") + +### Create Group +Group_2 = model.addGroup(Part_1_doc, "FACE", [model.selection("FACE", "Plaque/To_Face")]) +Group_2.setName("face_Zp") +Group_2.result().setName("face_Zp") + +### Create Group +Group_3 = model.addGroup(Part_1_doc, "FACE", [model.selection("FACE", "Plaque/Generated_Face&Sketch_1/SketchLine_1")]) +Group_3.setName("gauche") +Group_3.result().setName("gauche") + +### Create Group +Group_4 = model.addGroup(Part_1_doc, "FACE", [model.selection("FACE", "Plaque/Generated_Face&Sketch_1/SketchLine_2")]) +Group_4.setName("haut") +Group_4.result().setName("haut") + +### Create Group +Group_5 = model.addGroup(Part_1_doc, "FACE", [model.selection("FACE", "Plaque/Generated_Face&Sketch_1/SketchLine_3")]) +Group_5.setName("droite") +Group_5.result().setName("droite") + +### Create Group +Group_6 = model.addGroup(Part_1_doc, "FACE", [model.selection("FACE", "Plaque/Generated_Face&Sketch_1/SketchLine_4")]) +Group_6.setName("bas") +Group_6.result().setName("bas") + +### Create Group +Group_7 = model.addGroup(Part_1_doc, "FACE", [model.selection("FACE", "Plaque/Generated_Face&Sketch_1/SketchArc_1_2")]) +Group_7.setName("trou") +Group_7.result().setName("trou") + +### Create Group +Group_8 = model.addGroup(Part_1_doc, "EDGE", [model.selection("EDGE", "[Plaque/Generated_Face&Sketch_1/SketchArc_1_2][Plaque/From_Face]")]) +Group_8.setName("arc_Zm") +Group_8.result().setName("arc_Zm") + +### Create Group +Group_9 = model.addGroup(Part_1_doc, "EDGE", [model.selection("EDGE", "[Plaque/Generated_Face&Sketch_1/SketchArc_1_2][Plaque/To_Face]")]) +Group_9.setName("arc_Zp") +Group_9.result().setName("arc_Zp") + +### Create Group +Group_10 = model.addGroup(Part_1_doc, "EDGE", [model.selection("EDGE", "[Plaque/Generated_Face&Sketch_1/SketchArc_1_2][Plaque/Generated_Face&Sketch_1/SketchLine_4]")]) +Group_10.setName("verticale") +Group_10.result().setName("verticale") + +### Create Group +Group_11 = model.addGroup(Part_1_doc, "VERTEX", [model.selection("VERTEX", "[Plaque/Generated_Face&Sketch_1/SketchArc_1_2][Plaque/Generated_Face&Sketch_1/SketchLine_1][Plaque/From_Face]")]) +Group_11.setName("A") +Group_11.result().setName("A") + +### Create Group +Group_12 = model.addGroup(Part_1_doc, "VERTEX", [model.selection("VERTEX", "[Plaque/Generated_Face&Sketch_1/SketchArc_1_2][Plaque/Generated_Face&Sketch_1/SketchLine_4][Plaque/From_Face]")]) +Group_12.setName("B") +Group_12.result().setName("B") + +model.end() + + +if salome.sg.hasDesktop(): + salome.sg.updateObjBrowser() diff --git a/src/SAMConverter/Test/data/predict_engine_mock_scenario1.py b/src/SAMConverter/Test/data/predict_engine_mock_scenario1.py new file mode 100644 index 000000000..21781c28f --- /dev/null +++ b/src/SAMConverter/Test/data/predict_engine_mock_scenario1.py @@ -0,0 +1,43 @@ +# Copyright (C) 2014-2022 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# AIEngine mock for scenario 1 + +class AIEngine: + + ## The constructor. + def __init__(self): + pass + + def Predict(self, sam_model): + print('AIEngine.Predict() !!!') + + circle = sam_model.sequence[1] + line_1 = sam_model.sequence[3] + line_4 = sam_model.sequence[9] + line_5 = sam_model.sequence[13] + line_8 = sam_model.sequence[19] + + prediction = {"SUGGESTION_1" : { 'primitives' : [line_1, line_4], 'suggested_constraint' : 'ANGLE', 'score' : 0.98 }, + "SUGGESTION_2" : { 'primitives' : [circle], 'suggested_constraint' : 'RADIUS', 'score' : 0.58 }, + "SUGGESTION_3" : { 'primitives' : [line_8, line_1], 'suggested_constraint' : 'EQUAL', 'score' : 0.4 }, + "SUGGESTION_4" : { 'primitives' : [line_5, line_1], 'suggested_constraint' : 'DISTANCE', 'score' : 0.01 }, + } + + return prediction diff --git a/src/SAMConverter/Test/data/predict_engine_mock_scenario2.py b/src/SAMConverter/Test/data/predict_engine_mock_scenario2.py new file mode 100644 index 000000000..f20d4a932 --- /dev/null +++ b/src/SAMConverter/Test/data/predict_engine_mock_scenario2.py @@ -0,0 +1,43 @@ +# Copyright (C) 2014-2022 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# AIEngine mock + +class AIEngine: + + ## The constructor. + def __init__(self): + pass + + def Predict(self, sam_model): + print('AIEngine.Predict() !!!') + + line_1 = sam_model.sequence[0] + line_2 = sam_model.sequence[1] + line_3 = sam_model.sequence[3] + line_4 = sam_model.sequence[5] + line_5 = sam_model.sequence[6] + line_8 = sam_model.sequence[7] + + prediction = {"SUGGESTION_1" : { 'primitives' : [line_1, line_4], 'suggested_constraint' : 'COINCIDENCE', 'score' : 0.6 }, + "SUGGESTION_2" : { 'primitives' : [line_4], 'suggested_constraint' : 'LENGHT', 'score' : 0.58 }, + "SUGGESTION_3" : { 'primitives' : [line_8, line_1], 'suggested_constraint' : 'EQUAL', 'score' : 0.4 }, + "SUGGESTION_4" : { 'primitives' : [line_4], 'suggested_constraint' : 'VERTICAL', 'score' : 0.01 }, + } + return prediction diff --git a/src/SAMConverter/Test/tests.set b/src/SAMConverter/Test/tests.set index 86799645c..54f312755 100644 --- a/src/SAMConverter/Test/tests.set +++ b/src/SAMConverter/Test/tests.set @@ -32,4 +32,6 @@ SET(TEST_NAMES TestSAMConverter_Radius TestSAMConverter_Sketch TestSAMConverter_VerticalDistance + TestSAMConverter_scenario1 + TestSAMConverter_scenario2 ) diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index 01cc1bc74..22f4e9201 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -368,6 +368,8 @@ std::shared_ptr SketchPlugin_Plugin aMsg->setState(SketchPlugin_Offset::ID(), aHasSketchPlane); // SketchRectangle is a python feature, so its ID is passed just as a string aMsg->setState("SketchRectangle", aHasSketchPlane); + // SuggestConstraints is a python feature, so its ID is passed just as a string + aMsg->setState("SuggestConstraints", aHasSketchPlane); } } return aMsg; -- 2.39.2