//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public FeatureReport SendToParts(AssemblyDocument ParentDocument, List <ComponentOccurrence> Participants, PartFeature AsmFeature) { RectangularPatternFeature patternFeature = AsmFeature as RectangularPatternFeature; switch (_PatternMigrationMode) { case PatternMigrationModeEnum.kSendToPartsAsCollectionMode: return(SendToPartsAsCollection(ParentDocument, Participants, patternFeature)); case PatternMigrationModeEnum.kSendToPartsAsPatternMode: return(SendToPartsAsPattern(ParentDocument, Participants, patternFeature)); default: return(null); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private static RectangularPatternFeature[] CopyRectangularPatternFeature(PartComponentDefinition partCompDef, RectangularPatternFeature AsmFeature, Matrix invTransfo, int elementIdx, ComponentOccurrence occurrence, out ReportData[] reports) { List <RectangularPatternFeature> newFeatures = new List <RectangularPatternFeature>(); ObjectCollection ParentFeatures = FeatureUtilities.CopyParentFeatures(partCompDef, AsmFeature.Parent.Document as Document, AsmFeature.ParentFeatures, invTransfo, occurrence, out reports); if (ParentFeatures.Count == 0) { return(null); } Sketch3D sketch3D = partCompDef.Sketches3D.Add(); List <RectangularPatternFeatureData> FeaturesDataList = new List <RectangularPatternFeatureData>(); //Only along X Axis if (AsmFeature.XDirectionEntity != null && AsmFeature.YDirectionEntity == null) { UnitVector xDirection = FeatureUtilities.GetDirection(AsmFeature.XDirectionEntity); xDirection.TransformBy(invTransfo); Point xDirStartPoint = null; WorkAxis xDirAxis = null; SketchPoint3D xDirStartPoint3D = null; try { xDirStartPoint = FeatureUtilities.GetPoint(AsmFeature.XDirectionStartPoint); xDirStartPoint.TransformBy(invTransfo); xDirAxis = partCompDef.WorkAxes.AddFixed(xDirStartPoint, xDirection, FeatureUtilities.ConstructionWorkAxis); xDirStartPoint3D = sketch3D.SketchPoints3D.Add(xDirStartPoint, false); } catch { xDirAxis = partCompDef.WorkAxes.AddFixed(partCompDef.WorkPoints[1].Point, xDirection, FeatureUtilities.ConstructionWorkAxis); } double count1 = (double)(AsmFeature.XCount.Value) - elementIdx + 1; //Check it's not the last pattern element if (count1 != 0 && elementIdx != (double)(AsmFeature.XCount.Value)) { RectangularPatternFeatureData featureData = newRectangularPatternFeatureData(); featureData.xCount = count1; featureData.xSpacing = AsmFeature.XSpacing.Value; featureData.naturalXDirection = AsmFeature.NaturalXDirection; featureData.xDirectionSpacingType = AsmFeature.XDirectionSpacingType; featureData.xDirAxis = xDirAxis; featureData.xDirStartPoint3D = xDirStartPoint3D; FeaturesDataList.Add(featureData); } double count2 = elementIdx; //Check it's not the first pattern element if (count2 != 0 && elementIdx != 1) { RectangularPatternFeatureData featureData = newRectangularPatternFeatureData(); featureData.xCount = count2; featureData.xSpacing = AsmFeature.XSpacing.Value; featureData.naturalXDirection = !AsmFeature.NaturalXDirection; featureData.xDirectionSpacingType = AsmFeature.XDirectionSpacingType; featureData.xDirAxis = xDirAxis; featureData.xDirStartPoint3D = xDirStartPoint3D; FeaturesDataList.Add(featureData); } } //Only along Y Axis if (AsmFeature.YDirectionEntity != null && AsmFeature.XDirectionEntity == null) { } //Only along both Axes if (AsmFeature.XDirectionEntity != null && AsmFeature.YDirectionEntity != null) { } foreach (RectangularPatternFeatureData featureData in FeaturesDataList) { RectangularPatternFeature newFeature = partCompDef.Features.RectangularPatternFeatures.Add(ParentFeatures, featureData.xDirAxis, featureData.naturalXDirection, featureData.xCount, featureData.xSpacing, featureData.xDirectionSpacingType, featureData.xDirStartPoint3D, featureData.yDirAxis, featureData.naturalYDirection, featureData.yCount, featureData.ySpacing, featureData.yDirectionSpacingType, featureData.yDirStartPoint3D, AsmFeature.ComputeType, AsmFeature.OrientationMethod); foreach (FeaturePatternElement element in newFeature.PatternElements) { if (newFeature.HealthStatus == HealthStatusEnum.kUpToDateHealth) { break; } if (element.Faces.Count == 0 && element.Index != 1) { element.Suppressed = true; } } if (newFeature != null) { newFeatures.Add(newFeature); } } return(newFeatures.ToArray()); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static FeatureReport SendToPartsAsCollection(AssemblyDocument ParentDocument, List <ComponentOccurrence> Participants, RectangularPatternFeature AsmFeature) { FeatureReport result = new FeatureReport(AsmFeature as PartFeature); if (FeatureUtilities.CreateBackupFile) { FeatureUtilities.BackupFile(Participants); } foreach (ComponentOccurrence occurrence in Participants) { if (!FeatureUtilities.IsValidOccurrence(occurrence)) { continue; } //Find if a pattern element affects this occurrence foreach (FeaturePatternElement element in AsmFeature.PatternElements) { bool affected = false; foreach (FaceProxy faceProxy in element.Faces) { if (faceProxy.ContainingOccurrence == occurrence) { affected = true; break; } } //first occurrence won't be migrated to parts. //Need to migrate parent feature for that if (!affected) { continue; } Matrix invTransfo = occurrence.Transformation; Matrix patternElemTransfo = element.Transform; patternElemTransfo.Invert(); invTransfo.TransformBy(patternElemTransfo); invTransfo.Invert(); PartComponentDefinition partCompDef = occurrence.Definition as PartComponentDefinition; ReportData[] reports = null; ObjectCollection ParentFeatures = FeatureUtilities.CopyParentFeatures(partCompDef, ParentDocument as Document, AsmFeature.ParentFeatures, invTransfo, occurrence, out reports); foreach (ReportData reportData in reports) { //Place Feature Tag: associativity handling //Not supported yet /*FeatureAttributeManager.CreatePartFeatureTag(ParentDocument, * AsmFeature as PartFeature, * reportData.PartFeature, * occurrence);*/ result.addReportData(reportData); } } } return(result); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static FeatureReport SendToPartsAsPattern(AssemblyDocument ParentDocument, List <ComponentOccurrence> Participants, RectangularPatternFeature AsmFeature) { FeatureReport result = new FeatureReport(AsmFeature as PartFeature); if (FeatureUtilities.CreateBackupFile) { FeatureUtilities.BackupFile(Participants); } foreach (ComponentOccurrence occurrence in Participants) { if (!FeatureUtilities.IsValidOccurrence(occurrence)) { continue; } bool loop = true; int elementIdx = 1; Matrix patternElemTransfo = FeatureUtilities.Application.TransientGeometry.CreateMatrix(); //Find first pattern element that affect this occurrence foreach (FeaturePatternElement element in AsmFeature.PatternElements) { foreach (FaceProxy faceProxy in element.Faces) { if (faceProxy.ContainingOccurrence == occurrence) { patternElemTransfo = element.Transform; patternElemTransfo.Invert(); elementIdx = element.Index; loop = false; break; } } if (!loop) { break; } } Matrix invTransfo = occurrence.Transformation; invTransfo.TransformBy(patternElemTransfo); invTransfo.Invert(); PartComponentDefinition partCompDef = occurrence.Definition as PartComponentDefinition; ReportData[] reports = null; RectangularPatternFeature[] newFeatures = CopyRectangularPatternFeature(partCompDef, AsmFeature, invTransfo, elementIdx, occurrence, out reports); foreach (ReportData reportData in reports) { result.addReportData(reportData); } foreach (RectangularPatternFeature newFeature in newFeatures) { result.addReportData(new ReportData(partCompDef.Document as PartDocument, newFeature as PartFeature)); } } return(result); }
private void Button_ok_Click(object sender, EventArgs e) { // references to some useful objects TransientGeometry geom = m_inventorApplication.TransientGeometry; //PartDocument document = m_inventorApplication.ActiveDocument as PartDocument; //_Document document = m_inventorApplication.ActiveDocument; /* * if (document == null) * { * AssemblyDocument asm = m_inventorApplication.ActiveDocument as AssemblyDocument; * m_inventorApplication.ActiveDocument; * } */ PartComponentDefinition def; // = document.ComponentDefinition; UnitsOfMeasure units; // = document.UnitsOfMeasure; UserParameters user_params; Document document = m_inventorApplication.ActiveDocument; if (m_inventorApplication.ActiveDocument is AssemblyDocument) { AssemblyDocument doc = m_inventorApplication.ActiveDocument as AssemblyDocument; PartDocument part = doc.ActivatedObject as PartDocument; if (part == null) { m_inventorApplication.ErrorManager.Show("Please activate a part!", true, false); return; } def = part.ComponentDefinition; units = part.UnitsOfMeasure; user_params = part.ComponentDefinition.Parameters.UserParameters; } else if (m_inventorApplication.ActiveDocument is PartDocument) { PartDocument doc = m_inventorApplication.ActiveDocument as PartDocument; def = doc.ComponentDefinition; units = doc.UnitsOfMeasure; user_params = doc.ComponentDefinition.Parameters.UserParameters; } else { m_inventorApplication.ErrorManager.Show("Current document is neither an Assembly nor a Part.", true, false); return; } // get and check selected faces ObjectsEnumerator JustSelectedEntities = m_selects.SelectedEntities; if (JustSelectedEntities.Count == 0) { m_inventorApplication.ErrorManager.Show("Select at least one planar, rectangular face.", true, false); return; } foreach (Object _f in JustSelectedEntities) { Face f = _f as Face; if (f == null) { m_inventorApplication.ErrorManager.Show("Somehow, you managed to select something that isn't a face. This should not happen, please report it.", true, false); return; } if (f.Edges.Count != 4) { m_inventorApplication.ErrorManager.Show("Please only select rectangular faces.", true, false); return; } } // TODO: catch exception when invalid was is entered UserParameter tab_user_constr; if (m_dialog.mode_count.Checked) { tab_user_constr = user_params.AddByExpression("tab_count", m_dialog.tab_size_input.Text, UnitsTypeEnum.kUnitlessUnits); } else { tab_user_constr = user_params.AddByExpression("tab_size", m_dialog.tab_size_input.Text, UnitsTypeEnum.kDefaultDisplayLengthUnits); } int total_operations = JustSelectedEntities.Count; WorkAxis[] extrusion_dir = new WorkAxis[total_operations]; bool[] long_edge_dir = new bool[total_operations]; PlanarSketch[] all_sketches = new PlanarSketch[total_operations]; Profile[] profile = new Profile[total_operations]; ExtrudeFeature[] extrusion = new ExtrudeFeature[total_operations]; TwoPointDistanceDimConstraint[] tab_length_constr = new TwoPointDistanceDimConstraint[total_operations]; TwoPointDistanceDimConstraint[] tab_widthdepth_constr = new TwoPointDistanceDimConstraint[total_operations]; TwoPointDistanceDimConstraint[] total_length_constr = new TwoPointDistanceDimConstraint[total_operations]; RectangularPatternFeature[] rect_pattern = new RectangularPatternFeature[total_operations]; Transaction transaction = m_inventorApplication.TransactionManager.StartTransaction(m_inventorApplication.ActiveDocument, "LaserTab"); // create extrusion feature for each face int i = 0; foreach (Object _f in JustSelectedEntities) { Face f = _f as Face; if (_f is FaceProxy) { f = ((FaceProxy)_f).NativeObject; } // TODO: make sure active document is a partDocument and ActiveEditObject is not a sketch (should be also a partDocument?) // TODO: wrap it all into a ClientFeature // TODO: maybe also wrap it in a Transaction? // create sketch PlanarSketch sketch = def.Sketches.Add(f, false); // don't project anything //PlanarSketch sketch = def.Sketches.Add(f, true); // project existing geometry //PlanarSketch sketch = def.Sketches.AddWithOrientation(f, long_edge, true, true, long_edge.StartVertex, true); Edge short_edge, long_edge; Vertex vert_origin, vert_short_end, vert_long_end; determine_orientation(f, out long_edge, out short_edge, out vert_origin, out vert_long_end, out vert_short_end); // remember wheter 'long_edge' starts or stops at 'P_orig' (which is important for the direction of the rectangular pattern) long_edge_dir[i] = long_edge.StartVertex == vert_origin; extrusion_dir[i] = def.WorkAxes.AddByLine(long_edge, true); // project important points SketchPoint P_orig = sketch.AddByProjectingEntity(vert_origin) as SketchPoint; SketchPoint P_long = sketch.AddByProjectingEntity(vert_long_end) as SketchPoint; SketchPoint P_short = sketch.AddByProjectingEntity(vert_short_end) as SketchPoint; // fails! :( // driven constraint of short dimension (determining thickness and depth of tab) tab_widthdepth_constr[i] = sketch.DimensionConstraints.AddTwoPointDistance( P_orig, P_short, DimensionOrientationEnum.kAlignedDim, P_short.Geometry, true); // driven constraint of long dimenstion (determining number/size of tabs) total_length_constr[i] = sketch.DimensionConstraints.AddTwoPointDistance( P_orig, P_long, DimensionOrientationEnum.kAlignedDim, P_long.Geometry, true); // appearantly, Profiles.AddForSolid() doesn't like lines that are made entirely out of projected points... (maybe because the line already exists?) SketchPoint P_orig_proj = P_orig, P_short_proj = P_short; P_short = sketch.SketchPoints.Add(P_short_proj.Geometry, false); P_orig = sketch.SketchPoints.Add(P_orig_proj.Geometry, false); // create dimension constraints // TODO: calculate better position for text label //Debug.Print("constraint short: {0} = {1}", constr_short.Parameter.Expression, constr_short.Parameter.Value); //Debug.Print("constraint long: {0} = {1}", constr_long.Parameter.Expression, constr_long.Parameter.Value); // create endpoint for rectangle Point2d P_end2 = P_short.Geometry.Copy(); Point2d P_end1 = P_orig.Geometry.Copy(); Vector2d long_direction = P_orig.Geometry.VectorTo(P_long.Geometry); long_direction.ScaleBy(0.2); P_end1.TranslateBy(long_direction); P_end2.TranslateBy(long_direction); SketchPoint P_end1_sk = sketch.SketchPoints.Add(P_end1, false); SketchPoint P_end2_sk = sketch.SketchPoints.Add(P_end2, false); // constrain endpoints properly //sketch.GeometricConstraints.AddCoincident((SketchEntity)long_line2, (SketchEntity)P_end2_sk); //sketch.GeometricConstraints.AddCoincident((SketchEntity)long_line, (SketchEntity)P_end1_sk); // constraint for tab length (twice, once for each side of the rectangle) TwoPointDistanceDimConstraint tab_len_constraint1 = sketch.DimensionConstraints.AddTwoPointDistance(P_orig, P_end1_sk, DimensionOrientationEnum.kAlignedDim, P_end1); TwoPointDistanceDimConstraint tab_len_constraint2 = sketch.DimensionConstraints.AddTwoPointDistance(P_short, P_end2_sk, DimensionOrientationEnum.kAlignedDim, P_end2); tab_length_constr[i] = tab_len_constraint1; // {0}: total length // {1}: user input (count or length of single tab) string expr; if (m_dialog.mode_count.Checked) { if (m_dialog.force_parity.Checked) { if (m_dialog.parity_even.Checked) { expr = "{0} / ( round({1}/2)*2 )"; } else { expr = "{0} / ( round( ({1}+1)/2 )*2 - 1 )"; } } else { expr = "{0} / {1}"; } } else { // TODO: take dropdown of >/</~ into account if (m_dialog.force_parity.Checked) { if (m_dialog.parity_even.Checked) { expr = "{0} / ( round( {0}/{1}/2 )*2 )"; } else { expr = "{0} / ( round( ({0}/{1}+1)/2 )*2 - 1)"; } } else { expr = "{0} / round({0}/{1})"; } } tab_len_constraint1.Parameter.Expression = string.Format(expr, total_length_constr[i].Parameter.Name, tab_user_constr.Name); tab_len_constraint2.Parameter.Expression = tab_len_constraint1.Parameter.Name; // create a rectangle based on these points // two-point rectangle is always axis-aligned -> doesn't work for rotated stuff //SketchEntitiesEnumerator rect = sketch.SketchLines.AddAsTwoPointRectangle(P_orig, P_end_sk); // this is cumbersome, as the third point is transient and therefore the rectangle would have to be constrained afterwards //SketchEntitiesEnumerator rect = sketch.SketchLines.AddAsThreePointRectangle(P_orig, P_short, P_end); ObjectCollection rect = m_inventorApplication.TransientObjects.CreateObjectCollection(); rect.Add(sketch.SketchLines.AddByTwoPoints(P_orig, P_end1_sk)); rect.Add(sketch.SketchLines.AddByTwoPoints(P_end1_sk, P_end2_sk)); rect.Add(sketch.SketchLines.AddByTwoPoints(P_end2_sk, P_short)); rect.Add(sketch.SketchLines.AddByTwoPoints(P_short, P_orig)); // constrain rectangle if (m_dialog.offset.Checked) { sketch.GeometricConstraints.AddCoincident((SketchEntity)rect[1], (SketchEntity)P_orig_proj); sketch.GeometricConstraints.AddCoincident((SketchEntity)rect[3], (SketchEntity)P_short_proj); sketch.GeometricConstraints.AddPerpendicular((SketchEntity)rect[1], (SketchEntity)rect[2]); TwoPointDistanceDimConstraint offset_dist = sketch.DimensionConstraints.AddTwoPointDistance(P_orig, P_orig_proj, DimensionOrientationEnum.kAlignedDim, P_orig_proj.Geometry); offset_dist.Parameter.Expression = tab_len_constraint1.Parameter.Name; } else { sketch.GeometricConstraints.AddCoincident((SketchEntity)P_short, (SketchEntity)P_short_proj); sketch.GeometricConstraints.AddCoincident((SketchEntity)P_orig, (SketchEntity)P_orig_proj); } sketch.GeometricConstraints.AddCoincident((SketchEntity)rect[1], (SketchEntity)P_long); sketch.GeometricConstraints.AddParallel((SketchEntity)rect[1], (SketchEntity)rect[3]); profile[i] = sketch.Profiles.AddForSolid(false, rect); all_sketches[i] = sketch; i++; } // do extrusions for (i = 0; i < total_operations; i++) { string dist_expr; if (m_dialog.auto_depth.Checked) { // use thickness of material dist_expr = tab_widthdepth_constr[i].Parameter.Name; } else { // use user input // TODO: validate! dist_expr = m_dialog.tab_depth_input.Text; } PartFeatureExtentDirectionEnum dir; PartFeatureOperationEnum op; if (m_dialog.extrude_positive.Checked) { dir = PartFeatureExtentDirectionEnum.kPositiveExtentDirection; op = PartFeatureOperationEnum.kJoinOperation; } else { dir = PartFeatureExtentDirectionEnum.kNegativeExtentDirection; op = PartFeatureOperationEnum.kCutOperation; } // extrude said rectangle ExtrudeDefinition extrusion_def = def.Features.ExtrudeFeatures.CreateExtrudeDefinition(profile[i], op); extrusion_def.SetDistanceExtent(dist_expr, dir); extrusion[i] = def.Features.ExtrudeFeatures.Add(extrusion_def); } // do rectangular patterns for (i = 0; i < total_operations; i++) { // now repeat that extrusion ObjectCollection col = m_inventorApplication.TransientObjects.CreateObjectCollection(); col.Add(extrusion[i]); // TODO: is ceil() actually correct here? string offset = (m_dialog.offset.Checked ? "1" : "0"); string count_expr = string.Format("ceil(round({0} / {1} - {2}) / 2)", total_length_constr[i].Parameter.Name, tab_length_constr[i].Parameter.Name, offset); RectangularPatternFeatureDefinition pattern_def = def.Features.RectangularPatternFeatures.CreateDefinition( col, extrusion_dir[i], long_edge_dir[i], count_expr, tab_length_constr[i].Parameter.Name + "*2"); // TODO: we could use PatternSpacingType kFitToPathLength here... try { rect_pattern[i] = def.Features.RectangularPatternFeatures.AddByDefinition(pattern_def); } catch (Exception ex) { Debug.Print("rect pattern failed: {0}", ex.Message); Debug.Print("long edge: {0}, dir: {1}, count_expr = '{2}', len = '{3}'", extrusion_dir[i], long_edge_dir[i], count_expr, tab_length_constr[i].Parameter.Name + "*2"); transaction.End(); return; } } stop_selection(); // create custom feature (called a ClientFeature by Inventor) containing all our sketches, extrusions and patterns in a single node object start_element; if (total_operations == 1) { // if there is only a single operation, the tree looks like this: /* * - extrusion 1 (consumed sketch 1) * - pattern 1 */ start_element = extrusion[0]; } else { // if there are multiple operations, the sketch is not consumed by the extrusion // and the tree looks like this: /* * - sketch 1 * - sketch 2 * - extrusion 1 * - extrusion 2 * - pattern 1 * - pattern 2 */ start_element = all_sketches[0]; } ClientFeatureDefinition feature_def = def.Features.ClientFeatures.CreateDefinition("LaserTab", start_element, rect_pattern[total_operations - 1]); ClientFeature feature = def.Features.ClientFeatures.Add(feature_def, "{0defbf22-e302-4266-9bc9-fb80d5c8eb7e}"); // load the icon for our custom feature if not done so already if (m_browser_icon == null) { stdole.IPictureDisp icon = PictureConverter.ImageToPictureDisp(Properties.Resources.browser_icon_16); m_browser_icon = document.BrowserPanes.ClientNodeResources.Add("{0defbf22-e302-4266-9bc9-fb80d5c8eb7e}", -1, icon); } NativeBrowserNodeDefinition ndef = document.BrowserPanes[1].GetBrowserNodeFromObject(feature).BrowserNodeDefinition as NativeBrowserNodeDefinition; ndef.OverrideIcon = m_browser_icon; transaction.End(); }