コード例 #1
0
        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));
        }