public override FScheme.Value Evaluate(FSharpList<FScheme.Value> args) { //Solid argument bool isSolid = ((FScheme.Value.Number)args[0]).Item == 1; //Surface argument bool isSurface = ((FScheme.Value.Number)args[2]).Item == 1; //Build up our list of list of references for the form by... var curvesListList = (FScheme.Value.List)args[1]; //Now we add all of those references into ReferenceArrays ReferenceArrayArray refArrArr = new ReferenceArrayArray(); FSharpList<FScheme.Value> vals = ((FScheme.Value.List)curvesListList).Item; if (vals.Any() && (vals[0] is FScheme.Value.Container) && ((FScheme.Value.Container)vals[0]).Item is ModelCurveArray) { //Build a sequence that unwraps the input list from it's Value form. IEnumerable<ModelCurveArray> modelCurveArrays = ((FScheme.Value.List)args[1]).Item.Select( x => (ModelCurveArray)((FScheme.Value.Container)x).Item ); foreach (var modelCurveArray in modelCurveArrays) { var refArr = new ReferenceArray(); foreach (Autodesk.Revit.DB.ModelCurve modelCurve in modelCurveArray) { refArr.Append(modelCurve.GeometryCurve.Reference); } refArrArr.Append(refArr); } } else { IEnumerable<IEnumerable<Reference>> refArrays = (curvesListList).Item.Select( //...first selecting everything in the topmost list... delegate(FScheme.Value x) { //If the element in the topmost list is a sub-list... if (x.IsList) { //...then we return a new IEnumerable of References by converting the sub list. return (x as FScheme.Value.List).Item.Select( delegate(FScheme.Value y) { //Since we're in a sub-list, we can assume it's a container. var item = ((FScheme.Value.Container)y).Item; if (item is CurveElement) return (item as CurveElement).GeometryCurve.Reference; else return (Reference)item; } ); } //If the element is not a sub-list, then just assume it's a container. else { var obj = ((FScheme.Value.Container)x).Item; Reference r; if (obj is CurveElement) { r = (obj as CurveElement).GeometryCurve.Reference; } else { r = (Reference)obj; } //We return a list here since it's expecting an IEnumerable<Reference>. In reality, //just passing the element by itself instead of a sub-list is a shortcut for having //a list with one element, so this is just performing that for the user. return new List<Reference>() { r }; } } ); //Now we add all of those references into ReferenceArrays foreach (IEnumerable<Reference> refs in refArrays.Where(x => x.Any())) { var refArr = new ReferenceArray(); foreach (Reference r in refs) refArr.Append(r); refArrArr.Append(refArr); } } //If we already have a form stored... if (this.Elements.Any()) { Form oldF; //is this same element? if (dynUtils.TryGetElement(this.Elements[0], out oldF)) { if (oldF.IsSolid == isSolid && _preferSurfaceForOneLoop == isSurface && matchOrAddFormCurveToReferenceCurveMap(oldF, refArrArr, true)) { return FScheme.Value.NewContainer(oldF); } } //Dissolve it, we will re-make it later. if (FormUtils.CanBeDissolved(this.UIDocument.Document, this.Elements.Take(1).ToList())) FormUtils.DissolveForms(this.UIDocument.Document, this.Elements.Take(1).ToList()); //And register the form for deletion. Since we've already deleted it here manually, we can //pass "true" as the second argument. this.DeleteElement(this.Elements[0], true); } else if (this._formId != ElementId.InvalidElementId) { Form oldF; if (dynUtils.TryGetElement(this._formId, out oldF)) { if (oldF.IsSolid == isSolid && _preferSurfaceForOneLoop == isSurface && matchOrAddFormCurveToReferenceCurveMap(oldF, refArrArr, true)) { return FScheme.Value.NewContainer(oldF); } } } _preferSurfaceForOneLoop = isSurface; //We use the ReferenceArrayArray to make the form, and we store it for later runs. Form f; //if we only have a single refArr, we can make a capping surface or an extrusion if (refArrArr.Size == 1) { ReferenceArray refArr = refArrArr.get_Item(0); if (isSurface) // make a capping surface { f = this.UIDocument.Document.FamilyCreate.NewFormByCap(true, refArr); } else // make an extruded surface { // The extrusion form direction XYZ direction = new XYZ(0, 0, 50); f = this.UIDocument.Document.FamilyCreate.NewExtrusionForm(true, refArr, direction); } } else // make a lofted surface { f = this.UIDocument.Document.FamilyCreate.NewLoftForm(isSolid, refArrArr); } matchOrAddFormCurveToReferenceCurveMap(f, refArrArr, false); this.Elements.Add(f.Id); return FScheme.Value.NewContainer(f); }
bool matchOrAddFormCurveToReferenceCurveMap(Form formElement, ReferenceArrayArray refArrArr, bool doMatch) { if (formElement.Id != _formId && doMatch) { return false; } else if (!doMatch) _formId = formElement.Id; if (doMatch && _sformCurveToReferenceCurveMap.Count == 0) return false; else if (!doMatch) _sformCurveToReferenceCurveMap = new Dictionary<ElementId, ElementId>(); for (int indexRefArr = 0; indexRefArr < refArrArr.Size; indexRefArr++) { if (indexRefArr >= refArrArr.Size) { if (!doMatch) _sformCurveToReferenceCurveMap.Clear(); return false; } if (refArrArr.get_Item(indexRefArr).Size != formElement.get_CurveLoopReferencesOnProfile(indexRefArr, 0).Size) { if (!doMatch) _sformCurveToReferenceCurveMap.Clear(); return false; } for (int indexRef = 0; indexRef < refArrArr.get_Item(indexRefArr).Size; indexRef++) { Reference oldRef = formElement.get_CurveLoopReferencesOnProfile(indexRefArr, 0).get_Item(indexRef); Reference newRef = refArrArr.get_Item(indexRefArr).get_Item(indexRef); if ((oldRef.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_NONE && oldRef.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_LINEAR) || (newRef.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_NONE && newRef.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_LINEAR) || oldRef.ElementReferenceType != newRef.ElementReferenceType) { if (!doMatch) _sformCurveToReferenceCurveMap.Clear(); return false; } ElementId oldRefId = oldRef.ElementId; ElementId newRefId = newRef.ElementId; if (doMatch && (!_sformCurveToReferenceCurveMap.ContainsKey(newRefId) || _sformCurveToReferenceCurveMap[newRefId] != oldRefId) ) { return false; } else if (!doMatch) _sformCurveToReferenceCurveMap[newRefId] = oldRefId; } } return true; }
public override Value Evaluate(FSharpList <Value> args) { //Solid argument bool isSolid = ((Value.Number)args[0]).Item == 1; //Surface argument bool isSurface = ((Value.Number)args[2]).Item == 1; //Build up our list of list of references for the form by... var curvesListList = (Value.List)args[1]; //Now we add all of those references into ReferenceArrays ReferenceArrayArray refArrArr = new ReferenceArrayArray(); FSharpList <Value> vals = ((Value.List)curvesListList).Item; if (vals.Any() && (vals[0] is Value.Container) && ((Value.Container)vals[0]).Item is ModelCurveArray) { //Build a sequence that unwraps the input list from it's Value form. IEnumerable <ModelCurveArray> modelCurveArrays = ((Value.List)args[1]).Item.Select( x => (ModelCurveArray)((Value.Container)x).Item ); foreach (var modelCurveArray in modelCurveArrays) { var refArr = new ReferenceArray(); foreach (ModelCurve modelCurve in modelCurveArray) { refArr.Append(modelCurve.GeometryCurve.Reference); } refArrArr.Append(refArr); } } else { IEnumerable <IEnumerable <Reference> > refArrays = (curvesListList).Item.Select( //...first selecting everything in the topmost list... delegate(Value x) { //If the element in the topmost list is a sub-list... if (x.IsList) { //...then we return a new IEnumerable of References by converting the sub list. return((x as Value.List).Item.Select( delegate(Value y) { //Since we're in a sub-list, we can assume it's a container. var item = ((Value.Container)y).Item; if (item is CurveElement) { return (item as CurveElement).GeometryCurve.Reference; } else { return (Reference)item; } } )); } //If the element is not a sub-list, then just assume it's a container. else { var obj = ((Value.Container)x).Item; Reference r; if (obj is CurveElement) { r = (obj as CurveElement).GeometryCurve.Reference; } else { r = (Reference)obj; } //We return a list here since it's expecting an IEnumerable<Reference>. In reality, //just passing the element by itself instead of a sub-list is a shortcut for having //a list with one element, so this is just performing that for the user. return(new List <Reference>() { r }); } } ); //Now we add all of those references into ReferenceArrays foreach (IEnumerable <Reference> refs in refArrays.Where(x => x.Any())) { var refArr = new ReferenceArray(); foreach (Reference r in refs) { refArr.Append(r); } refArrArr.Append(refArr); } } //If we already have a form stored... if (this.Elements.Any()) { //is this same element? Element e = null; if (dynUtils.TryGetElement(this.Elements[0], typeof(Form), out e) && e != null && e is Form) { Form oldF = (Form)e; if (oldF.IsSolid == isSolid && preferSurfaceForOneLoop == isSurface && matchOrAddFormCurveToReferenceCurveMap(oldF, refArrArr, true)) { return(Value.NewContainer(oldF)); } } //Dissolve it, we will re-make it later. if (FormUtils.CanBeDissolved(this.UIDocument.Document, this.Elements.Take(1).ToList())) { FormUtils.DissolveForms(this.UIDocument.Document, this.Elements.Take(1).ToList()); } //And register the form for deletion. Since we've already deleted it here manually, we can //pass "true" as the second argument. this.DeleteElement(this.Elements[0], true); } else if (this.formId != ElementId.InvalidElementId) { Element e = null; if (dynUtils.TryGetElement(this.formId, typeof(Form), out e) && e != null && e is Form) { Form oldF = (Form)e; if (oldF.IsSolid == isSolid && preferSurfaceForOneLoop == isSurface && matchOrAddFormCurveToReferenceCurveMap(oldF, refArrArr, true)) { return(Value.NewContainer(oldF)); } } } preferSurfaceForOneLoop = isSurface; //We use the ReferenceArrayArray to make the form, and we store it for later runs. Form f; //if we only have a single refArr, we can make a capping surface or an extrusion if (refArrArr.Size == 1) { ReferenceArray refArr = refArrArr.get_Item(0); if (isSurface) // make a capping surface { f = this.UIDocument.Document.FamilyCreate.NewFormByCap(true, refArr); } else // make an extruded surface { // The extrusion form direction XYZ direction = new XYZ(0, 0, 50); f = this.UIDocument.Document.FamilyCreate.NewExtrusionForm(true, refArr, direction); } } else // make a lofted surface { f = this.UIDocument.Document.FamilyCreate.NewLoftForm(isSolid, refArrArr); } matchOrAddFormCurveToReferenceCurveMap(f, refArrArr, false); this.Elements.Add(f.Id); return(Value.NewContainer(f)); }
bool matchOrAddFormCurveToReferenceCurveMap(Form formElement, ReferenceArrayArray refArrArr, bool doMatch) { if (formElement.Id != formId && doMatch) { return(false); } else if (!doMatch) { formId = formElement.Id; } if (doMatch && sformCurveToReferenceCurveMap.Count == 0) { return(false); } else if (!doMatch) { sformCurveToReferenceCurveMap = new Dictionary <ElementId, ElementId>(); } for (int indexRefArr = 0; indexRefArr < refArrArr.Size; indexRefArr++) { if (indexRefArr >= refArrArr.Size) { if (!doMatch) { sformCurveToReferenceCurveMap.Clear(); } return(false); } if (refArrArr.get_Item(indexRefArr).Size != formElement.get_CurveLoopReferencesOnProfile(indexRefArr, 0).Size) { if (!doMatch) { sformCurveToReferenceCurveMap.Clear(); } return(false); } for (int indexRef = 0; indexRef < refArrArr.get_Item(indexRefArr).Size; indexRef++) { Reference oldRef = formElement.get_CurveLoopReferencesOnProfile(indexRefArr, 0).get_Item(indexRef); Reference newRef = refArrArr.get_Item(indexRefArr).get_Item(indexRef); if ((oldRef.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_NONE && oldRef.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_LINEAR) || (newRef.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_NONE && newRef.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_LINEAR) || oldRef.ElementReferenceType != newRef.ElementReferenceType) { if (!doMatch) { sformCurveToReferenceCurveMap.Clear(); } return(false); } ElementId oldRefId = oldRef.ElementId; ElementId newRefId = newRef.ElementId; if (doMatch && (!sformCurveToReferenceCurveMap.ContainsKey(newRefId) || sformCurveToReferenceCurveMap[newRefId] != oldRefId) ) { return(false); } else if (!doMatch) { sformCurveToReferenceCurveMap[newRefId] = oldRefId; } } } return(true); }
public override Expression Evaluate(FSharpList<Expression> args) { //If we already have a form stored... if (this.Elements.Any()) { //Dissolve it, we will re-make it later. FormUtils.DissolveForms(this.UIDocument.Document, this.Elements.Take(1).ToList()); //And register the form for deletion. Since we've already deleted it here manually, we can //pass "true" as the second argument. this.DeleteElement(this.Elements[0], true); } //Solid argument bool isSolid = ((Expression.Number)args[0]).Item == 1; //Surface argument bool isSurface = ((Expression.Number)args[2]).Item == 1; //Build up our list of list of references for the form by... IEnumerable<IEnumerable<Reference>> refArrays = ((Expression.List)args[1]).Item.Select( //...first selecting everything in the topmost list... delegate(Expression x) { //If the element in the topmost list is a sub-list... if (x.IsList) { //...then we return a new IEnumerable of References by converting the sub list. return (x as Expression.List).Item.Select( delegate(Expression y) { //Since we're in a sub-list, we can assume it's a container. var item = ((Expression.Container)y).Item; if (item is CurveElement) return (item as CurveElement).GeometryCurve.Reference; else return (Reference)item; } ); } //If the element is not a sub-list, then just assume it's a container. else { var obj = ((Expression.Container)x).Item; Reference r; if (obj is CurveElement) { r = (obj as CurveElement).GeometryCurve.Reference; } else { r = (Reference)obj; } //We return a list here since it's expecting an IEnumerable<Reference>. In reality, //just passing the element by itself instead of a sub-list is a shortcut for having //a list with one element, so this is just performing that for the user. return new List<Reference>() { r }; } } ); //Now we add all of those references into ReferenceArrays ReferenceArrayArray refArrArr = new ReferenceArrayArray(); foreach (IEnumerable<Reference> refs in refArrays.Where(x => x.Any())) { var refArr = new ReferenceArray(); foreach (Reference r in refs) refArr.Append(r); refArrArr.Append(refArr); } //We use the ReferenceArrayArray to make the form, and we store it for later runs. Form f; //if we only have a single refArr, we can make a capping surface or an extrusion if (refArrArr.Size == 1) { ReferenceArray refArr = refArrArr.get_Item(0); if (isSurface) // make a capping surface { f = this.UIDocument.Document.FamilyCreate.NewFormByCap(true, refArr); } else // make an extruded surface { // The extrusion form direction XYZ direction = new XYZ(0, 0, 50); f = this.UIDocument.Document.FamilyCreate.NewExtrusionForm(true, refArr, direction); } } else // make a lofted surface { f = this.UIDocument.Document.FamilyCreate.NewLoftForm(isSolid, refArrArr); } this.Elements.Add(f.Id); return Expression.NewContainer(f); }