Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - (gile)

Pages: 1 [2] 3 4 ... 6
16
Selection sets / Re: Selection Ordinate Dimensions with Filter (dxf code)
« on: February 02, 2013, 02:27:08 PM »
Hi,

Look at the 70 dxf group.

Code: [Select]
TypedValue[] tvs = {
    new TypedValue(0, "dimension"),
    new TypedValue(3, "ISO-25"),
    new TypedValue(-4, "&="),
    new TypedValue(70, 6)};

SelectionFilter filter = new SelectioFilter(tvs);

PromptSelectionResult psr = ed.GetSelection(filter);

17
Blocks / Drag (attributed) block reference
« on: January 26, 2013, 10:44:15 PM »
Dragging and rotating an (attributed) block.

BlockJig is to be used to drag (and possibly rotate) a simple block.
While dragging the block, it's possible to dynamically rotate the block by pressing Ctrl.
A click terminate the process keeping the current position and rotation for the block

BlockAttribJig inherits from BlockJig and handles the block attribute references.
In the constructor, each attribute definition informations (position, alignement and rotation) is stored in a structure.
The overrided Update() method sets the attributes geometry according to the attribute definition informations and the block reference position and rotation.

Code: (csharp) [Select]
        class BlockJig : EntityJig
        {
            protected BlockReference _br;
            protected Point3d _pos;
            protected double _rot, _ucsRot;

            public BlockJig(BlockReference br)
                : base(br)
            {
                _br = br;
                _pos = _br.Position;
                Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
                CoordinateSystem3d ucs = ed.CurrentUserCoordinateSystem.CoordinateSystem3d;
                Matrix3d ocsMat = Matrix3d.WorldToPlane(new Plane(Point3d.Origin, ucs.Zaxis));
                _ucsRot = Vector3d.XAxis.GetAngleTo(ucs.Xaxis.TransformBy(ocsMat), ucs.Zaxis);
                _rot = _br.Rotation - _ucsRot;
            }

            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                System.Windows.Forms.Keys mods = System.Windows.Forms.Control.ModifierKeys;
                if ((mods & System.Windows.Forms.Keys.Control) > 0)
                {
                    JigPromptAngleOptions jpao =
                        new JigPromptAngleOptions("\nSpecify the rotation: ");
                    jpao.UseBasePoint = true;
                    jpao.BasePoint = _br.Position;
                    jpao.Cursor = CursorType.RubberBand;
                    jpao.UserInputControls = (
                        UserInputControls.Accept3dCoordinates |
                        UserInputControls.UseBasePointElevation);
                    PromptDoubleResult pdr = prompts.AcquireAngle(jpao);

                    if (_rot == pdr.Value)
                    {
                        return SamplerStatus.NoChange;
                    }
                    else
                    {
                        _rot = pdr.Value;
                        return SamplerStatus.OK;
                    }
                }
                else
                {
                    JigPromptPointOptions jppo =
                        new JigPromptPointOptions("\nSpecify insertion point (or press Ctrl for rotation): ");
                    jppo.UserInputControls =
                      (UserInputControls.Accept3dCoordinates | UserInputControls.NullResponseAccepted);
                    PromptPointResult ppr = prompts.AcquirePoint(jppo);
                    if (_pos.DistanceTo(ppr.Value) < Tolerance.Global.EqualPoint)
                    {
                        return SamplerStatus.NoChange;
                    }
                    else
                    {
                        _pos = ppr.Value;
                    }
                    return SamplerStatus.OK;
                }
            }

            protected override bool Update()
            {
                _br.Position = _pos;
                _br.Rotation = _rot +_ucsRot;
                return true;
            }
        }

        class BlockAttribJig : BlockJig
        {
            struct TextInfo
            {
                public Point3d Position;
                public Point3d Alignment;
                public double Rotation;
                public bool IsAligned;
            }

            private Dictionary<string, TextInfo> _attInfos;

            public BlockAttribJig(BlockReference br)
                : base(br)
            {
                _attInfos = new Dictionary<string, TextInfo>();
                BlockTableRecord btr = (BlockTableRecord)br.BlockTableRecord.GetObject(OpenMode.ForRead);
                foreach (ObjectId id in btr)
                {
                    if (id.ObjectClass.Name == "AcDbAttributeDefinition")
                    {
                        AttributeDefinition attDef = (AttributeDefinition)id.GetObject(OpenMode.ForRead);
                        TextInfo ti = new TextInfo()
                        {
                            Position = attDef.Position,
                            Alignment = attDef.AlignmentPoint,
                            IsAligned = attDef.Justify != AttachmentPoint.BaseLeft,
                            Rotation = attDef.Rotation
                        };
                        _attInfos.Add(attDef.Tag.ToUpper(), ti);
                    }
                }
            }

            protected override bool Update()
            {
                base.Update();
                foreach (ObjectId id in _br.AttributeCollection)
                {
                    AttributeReference att = (AttributeReference)id.GetObject(OpenMode.ForWrite);
                    att.Rotation = _br.Rotation;
                    string tag = att.Tag.ToUpper();
                    if (_attInfos.ContainsKey(tag))
                    {
                        TextInfo ti = _attInfos[tag];
                        att.Position = ti.Position.TransformBy(_br.BlockTransform);
                        if (ti.IsAligned)
                        {
                            att.AlignmentPoint =
                                ti.Alignment.TransformBy(_br.BlockTransform);
                            att.AdjustAlignment(_br.Database);
                        }
                        if (att.IsMTextAttribute)
                        {
                            att.UpdateMTextAttribute();
                        }
                        att.Rotation = ti.Rotation + _br.Rotation;
                    }
                }
                return true;
            }
        }

A little using example to insert a block

Code: (csharp) [Select]
        [CommandMethod("TEST")]
        public void Test()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptResult pr = ed.GetString("\nBlock name: ");
            if (pr.Status != PromptStatus.OK) return;
            string blockName = pr.StringResult;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (!bt.Has(blockName))
                {
                    ed.WriteMessage("\nNone block '{0}' in the document block table.", blockName);
                    return;
                }
                BlockTableRecord curSpace =
                    (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

                // Add the block reference to Database first
                BlockReference br = new BlockReference(Point3d.Origin, bt[blockName]);
                br.TransformBy(ed.CurrentUserCoordinateSystem);
                curSpace.AppendEntity(br);
                tr.AddNewlyCreatedDBObject(br, true);

                // Get the block definition
                BlockTableRecord btr =
                    (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
                BlockJig jig;
                if (btr.HasAttributeDefinitions)
                {
                    // Add attribute references to the block reference
                    foreach (ObjectId id in btr)
                    {
                        if (id.ObjectClass.Name == "AcDbAttributeDefinition")
                        {
                            AttributeDefinition attDef =
                                (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
                            AttributeReference attRef = new AttributeReference();
                            attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
                            ObjectId attId = br.AttributeCollection.AppendAttribute(attRef);
                            tr.AddNewlyCreatedDBObject(attRef, true);
                        }
                    }
                    // Create a BlockAttribJig instance
                    jig = new BlockAttribJig(br);
                }
                else
                {
                    // Create a BlockJig instance
                    jig = new BlockJig(br);
                }
                // Drag the block reference
                pr = ed.Drag(jig);
                if (pr.Status != PromptStatus.OK) br.Erase();
                tr.Commit();
            }
        }

18
Math and Geometry / Re: Geometry extensions
« on: January 21, 2013, 08:13:21 PM »
I updated the attachment and documentation in the first message.

19
Polylines / Fillet
« on: December 24, 2012, 05:05:41 PM »
Hi,

Here're two extension methods for the Polyline class to add an arc (fillet) at the specified vertex or at each vertex.

The main difference between C#, VB and F# is the way to loop for each vertex while adding some new ones: with C# a 'for' loop can be used because the condition is checked at each loop, this must be done with a 'while' loop in VB and the 'natural' way in F# is a tail recursive function.

C#
Code: [Select]
    public static class Extensions
    {
        // Adds an arc (fillet) at each vertex, if able.
        public static void FilletAll(this Polyline pline, double radius)
        {
            int i = pline.Closed ? 0 : 1;
            for (int j = 0; j < pline.NumberOfVertices - i; j += 1 + pline.FilletAt(j, radius))
            { }
        }

       // Adds an arc (fillet) at the specified vertex. Returns 1 if the operation succeeded, 0 if it failed.
        public static int FilletAt(this Polyline pline, int index, double radius)
        {
            int prev = index == 0 && pline.Closed ? pline.NumberOfVertices - 1 : index - 1;
            if (pline.GetSegmentType(prev) != SegmentType.Line ||
                pline.GetSegmentType(index) != SegmentType.Line)
                return 0;
            LineSegment2d seg1 = pline.GetLineSegment2dAt(prev);
            LineSegment2d seg2 = pline.GetLineSegment2dAt(index);
            Vector2d vec1 = seg1.StartPoint - seg1.EndPoint;
            Vector2d vec2 = seg2.EndPoint - seg2.StartPoint;
            double angle = (Math.PI - vec1.GetAngleTo(vec2)) / 2.0;
            double dist = radius * Math.Tan(angle);
            if (dist > seg1.Length || dist > seg2.Length)
                return 0;
            Point2d pt1 = seg1.EndPoint + vec1.GetNormal() * dist;
            Point2d pt2 = seg2.StartPoint + vec2.GetNormal() * dist;
            double bulge = Math.Tan(angle / 2.0);
            if (Clockwise(seg1.StartPoint, seg1.EndPoint, seg2.EndPoint))
                bulge = -bulge;
            pline.AddVertexAt(index, pt1, bulge, 0.0, 0.0);
            pline.SetPointAt(index + 1, pt2);
            return 1;
        }

        // Evaluates if the points are clockwise.
        private static bool Clockwise(Point2d p1, Point2d p2, Point2d p3)
        {
            return ((p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X)) < 1e-8;
        }
    }

VB
Code: [Select]
    Module Extensions

        ' Adds an arc (fillet) at each polyline vertex, if able.
        <System.Runtime.CompilerServices.Extension> _
        Public Sub FilletAll(pline As Polyline, radius As Double)
            Dim i As Integer = If(pline.Closed, 0, 1)
            While i < If(pline.Closed, pline.NumberOfVertices, pline.NumberOfVertices - 1)
                i += 1 + pline.FilletAt(i, radius)
            End While
        End Sub

        ' Adds an arc (fillet) at the specified vertex. Retuns 1 if the operation succeeded, 0 if it failed.
        <System.Runtime.CompilerServices.Extension> _
        Public Function FilletAt(pline As Polyline, index As Integer, radius As Double) As Integer
            Dim prev As Integer = If(index = 0 AndAlso pline.Closed, pline.NumberOfVertices - 1, index - 1)
            If pline.GetSegmentType(prev) <> SegmentType.Line OrElse _
                pline.GetSegmentType(index) <> SegmentType.Line Then
                Return 0
            End If
            Dim seg1 As LineSegment2d = pline.GetLineSegment2dAt(prev)
            Dim seg2 As LineSegment2d = pline.GetLineSegment2dAt(index)
            Dim vec1 As Vector2d = seg1.StartPoint - seg1.EndPoint
            Dim vec2 As Vector2d = seg2.EndPoint - seg2.StartPoint
            Dim angle As Double = (Math.PI - vec1.GetAngleTo(vec2)) / 2.0
            Dim dist As Double = radius * Math.Tan(angle)
            If dist > seg1.Length OrElse dist > seg2.Length Then
                Return 0
            End If
            Dim pt1 As Point2d = seg1.EndPoint + vec1.GetNormal() * dist
            Dim pt2 As Point2d = seg2.StartPoint + vec2.GetNormal() * dist
            Dim bulge As Double = Math.Tan(angle / 2.0)
            If Clockwise(seg1.StartPoint, seg1.EndPoint, seg2.EndPoint) Then
                bulge = -bulge
            End If
            pline.AddVertexAt(index, pt1, bulge, 0.0, 0.0)
            pline.SetPointAt(index + 1, pt2)
            Return 1
        End Function

        ' Evaluates if the points are clockwise.
        Private Function Clockwise(p1 As Point2d, p2 As Point2d, p3 As Point2d) As Boolean
            Return ((p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X)) < 0.00000001
        End Function

    End Module

F#
Code: [Select]
// Evaluates if the points are clockwise.
let clockwise (p1: Point2d) (p2: Point2d) (p3: Point2d) =
    ((p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X)) < 1e-8

type Polyline with
    // Adds an arc (fillet) at the specified vertex. Retuns 1 if the operation succeeded, 0 if it failed.
    member pl.FilletAt index radius =
        let prev = (if index = 0 && pl.Closed then pl.NumberOfVertices else index) - 1
        if pl.GetSegmentType(prev) <> SegmentType.Line ||
            pl.GetSegmentType(index) <> SegmentType.Line then
            0
        else
            let seg1 = pl.GetLineSegment2dAt(prev)
            let seg2 = pl.GetLineSegment2dAt(index)
            let vec1 = seg1.StartPoint - seg1.EndPoint
            let vec2 = seg2.EndPoint - seg2.StartPoint
            let angle = (Math.PI - vec1.GetAngleTo(vec2)) / 2.
            let dist = radius * tan(angle)
            if dist > seg1.Length || dist > seg2.Length then
                0
            else
                let pt1 = seg1.EndPoint + vec1.GetNormal() * dist
                let pt2 = seg2.StartPoint + vec2.GetNormal() * dist
                let mutable bulge = tan(angle / 2.)
                if clockwise pt1 seg1.EndPoint pt2 then bulge <- -bulge
                pl.AddVertexAt(index, pt1, bulge, 0., 0.)
                pl.SetPointAt(index + 1, pt2)
                1

    // Adds an arc (fillet) at each vertex, if able.
    member pl.FilletAll radius =
        let rec loop i =
            if i < pl.NumberOfVertices then
                loop (i + 1 + pl.FilletAt i radius)
        loop (if pl.Closed then 0 else 1)

20
Events / Re: EventHandler for Entity Selection
« on: November 25, 2012, 03:04:18 PM »
Hi,

I do not understand what you're trying to do, but you'll find an example of using the SelectionAdded event here.

21
Events / Re: EventHandler for Entity Selection
« on: November 24, 2012, 05:34:30 PM »
Hi,

The Editor.SelectionAdded event is fired every time entities are added to a selection set.

22
External databases / Re: Saving Custom Data
« on: November 04, 2012, 03:27:28 PM »
Hi,

Don't use new as variable name, it's a C# operator/keyword.

You'd rather test if the extension dictionary and the xrecord already exist.

While AddCustomData method is defined within the same class as the command, you don't need to declare it 'static' and it's a better practice to declare it 'private' (or 'internal' if it has to be used outside of the class within the same project).
If you want this method to be reusable, you can define an extension method for the DBObject type which ca be called on any DBObject instance  as an instance method.

Here's a first example with a private AddCustomData() method

Code: [Select]
    public class Commands
    {
        [CommandMethod("Test1")]
        public void Test1()
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptEntityResult per = ed.GetEntity("\nSelect an entity: ");
            if (per.Status != PromptStatus.OK)
                return;
            AddCustomData(
                per.ObjectId,
                "CustomData",
                new TypedValue((int)DxfCode.Thickness, 5.0),
                new TypedValue((int)DxfCode.Real, 35.0));
        }

        private void AddCustomData(ObjectId id, string key, params TypedValue[] values)
        {
            Database db = id.Database;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                DBObject obj = tr.GetObject(id, OpenMode.ForRead);
                ObjectId dictId = obj.ExtensionDictionary;
                if (dictId == ObjectId.Null)
                {
                    obj.UpgradeOpen();
                    obj.CreateExtensionDictionary();
                    dictId = obj.ExtensionDictionary;
                }
                DBDictionary xdict = (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead);
                Xrecord xrec;
                if (xdict.Contains(key))
                {
                    xrec = (Xrecord)tr.GetObject((ObjectId)xdict[key], OpenMode.ForWrite);
                }
                else
                {
                    xdict.UpgradeOpen();
                    xrec = new Xrecord();
                    xdict.SetAt(key, xrec);
                    tr.AddNewlyCreatedDBObject(xrec, true);
                }
                xrec.Data = new ResultBuffer(values);
                tr.Commit();
            }
        }
    }

A second example using an extension method (this method have to be 'public static' and defined in a 'static' class):
Code: [Select]
    public class Commands
    {
        [CommandMethod("Test2")]
        public void Test2()
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptEntityResult per = ed.GetEntity("\nSelect an entity: ");
            if (per.Status != PromptStatus.OK)
                return;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                DBObject obj = tr.GetObject(per.ObjectId, OpenMode.ForRead);
                obj.SetXrecord(
                    "CustomData",
                    new TypedValue((int)DxfCode.Thickness, 5.0),
                    new TypedValue((int)DxfCode.Real, 35.0));
                tr.Commit();
            }
        }
    }

    public static class Extensions
    {
        public static void SetXrecord(this DBObject obj, string key, params TypedValue[] values)
        {
            Transaction tr = obj.Database.TransactionManager.TopTransaction;
            if (tr == null)
                throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NotTopTransaction);
            ObjectId dictId = obj.ExtensionDictionary;
            if (dictId == ObjectId.Null)
            {
                obj.UpgradeOpen();
                obj.CreateExtensionDictionary();
                dictId = obj.ExtensionDictionary;
            }
            DBDictionary xdict = (DBDictionary)tr.GetObject(dictId, OpenMode.ForRead);
            Xrecord xrec;
            if (xdict.Contains(key))
            {
                xrec = (Xrecord)tr.GetObject((ObjectId)xdict[key], OpenMode.ForWrite);
            }
            else
            {
                xdict.UpgradeOpen();
                xrec = new Xrecord();
                xdict.SetAt(key, xrec);
                tr.AddNewlyCreatedDBObject(xrec, true);
            }
            xrec.Data = new ResultBuffer(values);
        }
    }

23
DesignScript / Re: Some more curves
« on: November 01, 2012, 07:42:45 PM »
One more: a cylindrical helix.

The constructor arguments are:
  • the radius
  • the total height
  • the total angle, if the input is negative the helix turns clockwise

Code: [Select]
import("ProtoGeometry.dll");
import("Math.dll");

class Helix
{
    Curve : Curve;
    constructor FromRadiusHeightAngle(radius : double, height : double, totalAngle : double)
    {
        pi = 3.141592653589793;
        numPts = Math.Abs(Math.Round(totalAngle / 15)) + 1;
        step = height / (numPts - 1);
        ccw = Math.Sign(totalAngle);
        tanZ = (180 * height) / (pi * totalAngle * radius);
        startTan = Vector.ByCoordinates(0, ccw, ccw * tanZ);
        endTan = Vector.ByCoordinates(ccw * -Math.Sin(totalAngle), ccw * Math.Cos(totalAngle), ccw * tanZ);
        x = radius * Math.Cos(0 .. totalAngle .. #numPts);
        y = radius * Math.Sin(0 .. totalAngle .. #numPts);
        z = step * (0 .. numPts);
        Curve = BSplineCurve.ByPoints(Point.ByCoordinates(x, y, z), startTan, endTan);
    }
}

24
DesignScript / Some more curves
« on: October 24, 2012, 02:50:13 PM »
Hi,

DesignScript is relatively poor in native curves (Line, Arc, Circle and BSplineCurve).
I thought it might be interesting to define some others.
I tried to do this as classes with constructors, these classes may be required to evolve with the addition of new features.
The generated curves are spline whose control points or smoothing are calculated from the equations of these curves.

The Catenary, Ellipse, EllpticalArc and Parabola classes:
Code: [Select]
import("ProtoGeometry.dll");
import("Math.dll");
   
class Catenary
{
    Curve : Curve;
    Chord : double;
    Param : double;
    Sagitta : double;
    Length : double;
   
    def argCosh(x : double)
    {
        return = Math.Log(x + Math.Sqrt(x * x - 1));
    }

    constructor FromChordParam(chord : double, param : double, numPts : int)
    {
        Chord = chord;
        Param = param;
        Sagitta = param * Math.Cosh(chord / (2 * param)) - param;
        Length = 2 * param * Math.Sinh(chord / (2 * param));
        x = chord / -2..chord / 2..#numPts;
        y = param * Math.Cosh(x / param);
        Curve = BSplineCurve.ByPoints(Point.ByCoordinates(x, y, 0));
    }
   
    constructor FromLenthSagitta(length : double, sagitta : double, numPts : int)
    {
        Length = length;
        Sagitta = sagitta;
        Param = (length * length - 4 * sagitta * sagitta) / (8 * sagitta);
        Chord = 2 * Param * argCosh((sagitta + Param) / Param);
        x = Chord / -2..Chord / 2..#numPts;
        y = Param * Math.Cosh(x / Param);
        Curve = BSplineCurve.ByPoints(Point.ByCoordinates(x, y, 0));
    }
}

class Ellipse
{
    Curve : Curve;
   
    constructor FromRadii(majRadius : double, minRadius : double)
    {
        Curve = Circle.ByCenterPointRadius(Point.ByCoordinates(0, 0, 0), 1)
        .Transform(CoordinateSystem.WCS,
            CoordinateSystem.Identity().Scale(majRadius, minRadius, 1));
    }
}

class EllipticalArc
{
    Curve : Curve;
   
    constructor FromRadii(majRadius : double, minRadius : double, startAngle : double, sweepAngle : double)
    {
        endAngle = startAngle + sweepAngle;
        startParam = Math.Atan(majRadius * Math.Tan(startAngle) / minRadius);
        endParam = Math.Atan(majRadius * Math.Tan(endAngle) / minRadius);
        [Imperative]
        {
            if (startAngle == 0 || startAngle == 90 || startAngle == 180 || startAngle == 270 || startAngle == 360)
                startParam = startAngle;
            else if (startAngle > 90 && startAngle < 270)
                startParam = startParam + 180;
            if (endAngle == 0 || endAngle == 90 || endAngle == 180 || endAngle == 270 || endAngle == 360)
                endParam = endAngle;
        else if (endAngle > 90 && endAngle < 270)
                endParam = endParam + 180;
            if (endParam <= startParam)
                endParam = endParam + 360;
        }
        Curve = Arc.ByCenterPointRadiusAngle(Point.ByCoordinates(0, 0, 0),
            1, startParam, endParam - startParam, Vector.ByCoordinates(0, 0, 1))
            .Transform(CoordinateSystem.WCS,
            CoordinateSystem.Identity().Scale(majRadius, minRadius, 1));
    }
}

class Parabola
{
    Curve : Curve;
    Focus : Point;
   
    constructor FromChordSagitta(chord : double, sagitta : double, numPts : int, focusVisible : bool)
    {
        a = 4 * sagitta / (chord * chord);
        Focus = Point.ByCoordinates(0, 1 / (4 * a), 0).SetVisibility(focusVisible);
        x = chord / - 2..chord / 2..#numPts;
        y = a * x * x;
        Curve = BSplineCurve.ByPoints(Point.ByCoordinates(x, y, 0));
    }
}


Using examples

Ellipses with incremented major axis.

Code: [Select]
el = Ellipse.FromRadii(30..80..5, 30);



Parabolas with decremented chords and incrmented sagittas

Code: [Select]
parabs = Parabola.FromChordSagitta(200..100..-10, 20..120..10, 19, false);


 
Catenaries with incremented params.
Each curve is moved so that start and end point lies ont the X axis. This is done using the Param and Sagitta properties of the Catenary instance.

Code: [Select]
def catenar(chord : double, param : double, numPts : int)
{
    cat = Catenary.FromChordParam(chord, param, numPts);
    return = cat.Curve.Translate(0, -cat.Param - cat.Sagitta, 0);
}

cats = catenar(160, 35..75..#10, 19);



 

25
External databases / Re: Saving Custom Data
« on: October 16, 2012, 09:42:01 PM »
Hi,

To save data in a dwg, (X)Dictionary/Xrecord or Xdata is the way.

26
Tables / Get the MText object in a cell
« on: October 13, 2012, 06:40:44 PM »
Hi,

Here's a little class which extends the Cell type with a method to get the MText object the cell contains (if any, returns null otherwise).

Code: [Select]
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace TableSample
{
    static class Extensions
    {
        // Retourne l'objet MText contenu dans la cellule (ou null s'il nexiste pas).
        // Returns the MText object contained in the cell (or null if it don't exist).
        public static MText GetMtext(this Cell cell)
        {
            Table table = cell.ParentTable;
            Extents3d extents = cell.GetExtents().ToExtents3d();
            extents.TransformBy(table.BlockTransform.Inverse());
            BlockTableRecord btr = (BlockTableRecord)table.BlockTableRecord.GetObject(OpenMode.ForRead);
            RXClass mtextClass = RXClass.GetClass(typeof(MText));
            foreach (ObjectId id in btr)
            {
                if (id.ObjectClass == mtextClass)
                {
                    MText mtext = (MText)id.GetObject(OpenMode.ForRead);
                    if (mtext.Location.IsInside(extents))
                        return mtext;
                }
            }
            return null;
        }

        // Evalue si un point est à l'intérieur de la boite (BoundingBox).
        // Evaluates if the point is within the extents (BoundingBox).
        private static bool IsInside(this Point3d pt, Extents3d extents)
        {
            return
                pt.X >= extents.MinPoint.X &&
                pt.Y >= extents.MinPoint.Y &&
                pt.Z >= extents.MinPoint.Z &&
                pt.X <= extents.MaxPoint.X &&
                pt.Y <= extents.MaxPoint.Y &&
                pt.Z <= extents.MaxPoint.Z;
        }

        // Retourne la boite (BoundingBox) définie par la collection de points.
        // Returns the extents (BoundingBox) defined by the points collection
        private static Extents3d ToExtents3d(this Point3dCollection pts)
        {
            return pts.Cast<Point3d>()
                .Aggregate(new Extents3d(pts[0], pts[0]), (ext, pt) =>
                { ext.AddPoint(pt); return ext; });
        }
    }
}

Using example, assuming table is an AutoCAD Table object, row and column the indices of the cell row and column:
Code: [Select]
MText mtext = table.Cells[row, column].GetMtext();

27
Display / Re: Zoom in a new database
« on: August 31, 2012, 06:22:30 PM »
Hi rom1,

Nice trick.
I tried to go a little further and get this work whatever the current view (i.e. an isometric or orbited view).
The main trick is to transform points from World System Coordinates (WCS) to the view Display Coordinate System (DCS) as shown for ZoomObjects or in GeomtryExtensions Editor or Viewport extension methods.
On the other hand, it seems that Database.UpdateExt() is not mandatory. From the tests I did all work fine without calling it.

So, here're some extension methods (yes, I like this feature) used to set a zoom extents in a side Database model space.

Code: [Select]
        /// <summary>
        /// Returns the transformation matrix from the ViewportTableRecord DCS to WCS.
        /// </summary>
        /// <param name="view">The ViewportTableRecord instance this method applies to.</param>
        /// <returns>The DCS to WCS transformation matrix.</returns>
        public static Matrix3d EyeToWorld(this ViewportTableRecord view)
        {
            return
                Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
                Matrix3d.Displacement(view.Target - Point3d.Origin) *
                Matrix3d.PlaneToWorld(view.ViewDirection);
        }

        /// <summary>
        /// Returns the transformation matrix from the ViewportTableRecord WCS to DCS.
        /// </summary>
        /// <param name="view">The ViewportTableRecord instance this method applies to.</param>
        /// <returns>The WCS to DCS transformation matrix.</returns>
        public static Matrix3d WorldToEye(this ViewportTableRecord view)
        {
            return view.EyeToWorld().Inverse();
        }

        /// <summary>
        /// Sets a zoom extents of the Database model space
        /// </summary>
        /// <param name="db">The Database instance this method applies to.</param>
        public static void ZoomExtents(this Database db)
        {
            db.TileMode = true;
            Point2d scrSize = (Point2d)AcAp.GetSystemVariable("screensize");
            double ratio = scrSize.X / scrSize.Y;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            using (Line line = new Line(db.Extmin, db.Extmax))
            {
                ViewportTable vpt =
                    (ViewportTable)tr.GetObject(db.ViewportTableId, OpenMode.ForRead);
                ViewportTableRecord vptr =
                    (ViewportTableRecord)tr.GetObject(vpt["*Active"], OpenMode.ForWrite);
                Extents3d ext = line.GeometricExtents;
                ext.TransformBy(vptr.WorldToEye());
                Point2d pmin = new Point2d(ext.MinPoint.X, ext.MinPoint.Y);
                Point2d pmax = new Point2d(ext.MaxPoint.X, ext.MaxPoint.Y);
                double height = pmax.Y - pmin.Y;
                double width = pmax.X - pmin.X;
                if (width / height < ratio)
                {
                    vptr.Height = height;
                    vptr.Width = height * ratio;
                }
                else
                {
                    vptr.Width = width;
                    vptr.Height = width / ratio;
                }
                vptr.CenterPoint = pmin + (pmax - pmin) / 2.0;
                tr.Commit();
            }
        }

A test command example:
Code: [Select]
        [CommandMethod("zedb")]
        public void ZoomExtentsDb()
        {
            using (Database db = new Database())
            {
                db.ReadDwgFile(@"F:\Dessin1.dwg", System.IO.FileShare.ReadWrite, false, "");
                db.ZoomExtents();
                db.SaveAs(@"F:\Dessin1.dwg", DwgVersion.Current);
            }
        }

28
External databases / Import SymbolTableRecords
« on: August 21, 2012, 08:59:35 PM »
Hi,

A generic extension method to import SymbolTableRecord objects from a dwg (or dwt) file into a Database.

The ImportSymbolTableRecords() method extends the Database type, that's to say it can be called with the dot(.) operator from a Database instance.
It is generic because it can target any SymbolTable using a Type parameter.
The requiered arguments are the source file full path and ParamArray of strings (one or more SymbolTableRecord names).
The function returns an ObjectIdCollection containing the ObjectId of the cloned SymbolTableRecords (null/Nothing if none have been imported).

C#
Extension methods have to be defined within a static class, they have to be static and their first argument must use the 'this' keyword and be the same type as the extended one.

Code: [Select]
    public static class Extension
    {
        public static ObjectIdCollection ImportSymbolTableRecords<T>(
            this Database targetDb,
            string sourceFile,
            params string[] recordNames)
            where T : SymbolTable
        {
            using (Database sourceDb = new Database())
            {
                sourceDb.ReadDwgFile(sourceFile, System.IO.FileShare.Read, false, "");
                ObjectId sourceTableId, targetTableId;
                switch (typeof(T).Name)
                {
                    case "BlockTable":
                        sourceTableId = sourceDb.BlockTableId;
                        targetTableId = targetDb.BlockTableId;
                        break;
                    case "DimStyleTable":
                        sourceTableId = sourceDb.DimStyleTableId;
                        targetTableId = targetDb.DimStyleTableId;
                        break;
                    case "LayerTable":
                        sourceTableId = sourceDb.LayerTableId;
                        targetTableId = targetDb.LayerTableId;
                        break;
                    case "LinetypeTable":
                        sourceTableId = sourceDb.LinetypeTableId;
                        targetTableId = targetDb.LinetypeTableId;
                        break;
                    case "RegAppTable":
                        sourceTableId = sourceDb.RegAppTableId;
                        targetTableId = targetDb.RegAppTableId;
                        break;
                    case "TextStyleTable":
                        sourceTableId = sourceDb.TextStyleTableId;
                        targetTableId = targetDb.TextStyleTableId;
                        break;
                    case "UcsTable":
                        sourceTableId = sourceDb.UcsTableId;
                        targetTableId = targetDb.UcsTableId;
                        break;
                    case "ViewTable":
                        sourceTableId = sourceDb.ViewportTableId;
                        targetTableId = targetDb.ViewportTableId;
                        break;
                    case "ViewportTable":
                        sourceTableId = sourceDb.ViewportTableId;
                        targetTableId = targetDb.ViewportTableId;
                        break;
                    default:
                        throw new ArgumentException("Requires a concrete type derived from SymbolTable");
                }

                using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
                {
                    T sourceTable = (T)tr.GetObject(sourceTableId, OpenMode.ForRead);
                    ObjectIdCollection idCol = new ObjectIdCollection();
                    foreach (string name in recordNames)
                    {
                        if (sourceTable.Has(name))
                        {
                            idCol.Add(sourceTable[name]);
                        }
                    }
                    if (idCol.Count == 0)
                        return null;
                    IdMapping idMap = new IdMapping();
                    sourceDb.WblockCloneObjects(
                        idCol, targetTableId, idMap, DuplicateRecordCloning.Replace, false);
                    tr.Commit();
                    ObjectIdCollection retVal = new ObjectIdCollection();
                    foreach (ObjectId id in idCol)
                    {
                        if (idMap[id].IsCloned)
                        {
                            retVal.Add(idMap[id].Value);
                        }
                    }
                    return retVal.Count == 0 ? null : retVal;
                }
            }
        }
    }

Using example:
Code: [Select]
ObjectIdCollection result =
    db.ImportSymbolTableRecords<TextStyleTable>(@"F:\gile\Templates\Standard2010.dwt", "Arial_Std", "Romans_Std");

VB
Extension methods have to be defined within a module with the System.Runtime.CompilerServices.Extension() attribute. The first argument have to be the same type as the extended one.

Code: [Select]
    Module Extension
        <System.Runtime.CompilerServices.Extension()> _
        Public Function ImportSymbolTableRecords(Of T As SymbolTable) _
        (targetDb As Database, sourceFile As String, ParamArray recordNames As String()) _
        As ObjectIdCollection
            Using sourceDb As New Database()
                sourceDb.ReadDwgFile(sourceFile, System.IO.FileShare.Read, False, "")
                Dim sourceTableId As ObjectId, targetTableId As ObjectId
                Select Case GetType(T).Name
                    Case "BlockTable"
                        sourceTableId = sourceDb.BlockTableId
                        targetTableId = targetDb.BlockTableId
                        Exit Select
                    Case "DimStyleTable"
                        sourceTableId = sourceDb.DimStyleTableId
                        targetTableId = targetDb.DimStyleTableId
                        Exit Select
                    Case "LayerTable"
                        sourceTableId = sourceDb.LayerTableId
                        targetTableId = targetDb.LayerTableId
                        Exit Select
                    Case "LinetypeTable"
                        sourceTableId = sourceDb.LinetypeTableId
                        targetTableId = targetDb.LinetypeTableId
                        Exit Select
                    Case "RegAppTable"
                        sourceTableId = sourceDb.RegAppTableId
                        targetTableId = targetDb.RegAppTableId
                        Exit Select
                    Case "TextStyleTable"
                        sourceTableId = sourceDb.TextStyleTableId
                        targetTableId = targetDb.TextStyleTableId
                        Exit Select
                    Case "UcsTable"
                        sourceTableId = sourceDb.UcsTableId
                        targetTableId = targetDb.UcsTableId
                        Exit Select
                    Case "ViewTable"
                        sourceTableId = sourceDb.ViewportTableId
                        targetTableId = targetDb.ViewportTableId
                        Exit Select
                    Case "ViewportTable"
                        sourceTableId = sourceDb.ViewportTableId
                        targetTableId = targetDb.ViewportTableId
                        Exit Select
                    Case Else
                        Throw New ArgumentException("Requires a concrete type derived from SymbolTable")
                End Select

                Using tr As Transaction = sourceDb.TransactionManager.StartTransaction()
                    Dim sourceTable As T = DirectCast(tr.GetObject(sourceTableId, OpenMode.ForRead), T)
                    Dim idCol As New ObjectIdCollection()
                    For Each name As String In recordNames
                        If sourceTable.Has(name) Then
                            idCol.Add(sourceTable(name))
                        End If
                    Next
                    If idCol.Count = 0 Then
                        Return Nothing
                    End If
                    Dim idMap As New IdMapping()
                    sourceDb.WblockCloneObjects(idCol, targetTableId, idMap, DuplicateRecordCloning.Ignore, False)
                    tr.Commit()
                    Dim retVal As New ObjectIdCollection()
                    For Each id As ObjectId In idCol
                        If idMap(id).IsCloned Then
                            retVal.Add(idMap(id).Value)
                        End If
                    Next
                    If retVal.Count = 0 Then
                        Return Nothing
                    Else
                        Return retVal
                    End If
                End Using
            End Using
        End Function
    End Module

Using example:
Code: [Select]
Dim result As ObjectIdCollection = _
    db.ImportSymbolTableRecords(Of TextStyleTable)("F:\gile\Templates\Standard2010.dwt", "Arial_Std", "Romans_Std")

F#
F# type extensions allows to easily add any member to an existing type. I let you appreciate how much more concise is the code due to some specific features as tuple let bindings, pattern matching, aggregate operators ...

Code: [Select]
type Database with
    member db.ImportSymbolTableRecords<'T when 'T :> SymbolTable>(sourceFile, ([<ParamArray>] recordNames: string array)) =
        use sourceDb = new Database()
        sourceDb.ReadDwgFile(sourceFile, System.IO.FileShare.Read, false, "")
        let  sourceTableId, targetTableId =
            match typeof<'T>.Name with
            | "BlockTable" -> sourceDb.BlockTableId, db.BlockTableId
            | "DimStyleTable" -> sourceDb.DimStyleTableId, db.DimStyleTableId
            | "LayerTable" -> sourceDb.LayerTableId, db.LayerTableId
            | "LinetypeTable" -> sourceDb.LinetypeTableId, db.LinetypeTableId
            | "RegAppTable" -> sourceDb.RegAppTableId, db.RegAppTableId
            | "TextStyleTable" -> sourceDb.TextStyleTableId, db.TextStyleTableId
            | "UcsTable" -> sourceDb.UcsTableId, db.UcsTableId
            | "ViewTable" -> sourceDb.ViewTableId, db.ViewTableId
            | "ViewportTable" -> sourceDb.ViewportTableId, db.ViewportTableId
            | _ -> invalidArg typeof<'T>.Name "Requires a concrete type derived from SymbolTable"

        use tr = sourceDb.TransactionManager.StartTransaction()
        let sourceTable = tr.GetObject(sourceTableId, OpenMode.ForRead) :?> 'T
        let sourceIds = recordNames |> Array.choose(function
            | n when sourceTable.Has(n) -> Some(sourceTable.[n])
            | _ -> None)
        if sourceIds.Length = 0 then
            null
        else
            let idCol = new ObjectIdCollection(sourceIds)
            let idMap = new IdMapping()
            sourceDb.WblockCloneObjects(idCol, targetTableId, idMap, DuplicateRecordCloning.Replace, false)
            tr.Commit()
            let ids = sourceIds |> Array.choose(function
                | id when idMap.[id].IsCloned -> Some(idMap.[id].Value)
                | _ -> None)
            if ids.Length = 0 then
                null
            else
                new ObjectIdCollection(ids)

Using example:
Code: [Select]
let result =
    db.ImportSymbolTableRecords<TextStyleTable>(@"F:\gile\Templates\Standard2010.dwt", "Arial_Std", "Romans_Std")

29
3D entities / Re: Create 3D solid by extruding a polyline
« on: August 09, 2012, 06:42:16 AM »
Hi Oleg,

In my opnion, there's no need to explode the polyline, it can be passed as is to the Region.CreateFromCurves() method.

Anyway, you may explicitely dispose the DBObjectCollections (lines and regions) in case ther're some objects left for which no managed wrapper have been created.
You must explicitely dispose each region used to create a solid as a managed wrapped is creadted and is not added to the Database (the same for the curves used to create the region as you explode the polyline).

The following code is extract from a topic at TheSwamp about "To dispose or not To Dispose" (reply #82).
It's quite closed to yours and try to cover most of the 'disposing or not' issues.

C#
Code: [Select]
        public void ExtrudePline()
        {
            // Never dispose Document nor Document.Editor
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            // Never dispose Database when the drawing is opened in the Editor
            // On the other hand, always dispose Database created with the constructor, i.e. new Database()
            Database db = doc.Database;

            // Always dispose DocumentLock
            using (doc.LockDocument())
            // Always dispose Transaction
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                // No need to dispose a DBObject opened from a transaction
                BlockTableRecord currentSpace =
                    (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

                // Always dispose a new DBObject which may not be added to the database
                using (Polyline pline = new Polyline())
                {
                    pline.AddVertexAt(0, Point2d.Origin, 0.0, 0.0, 0.0);
                    pline.AddVertexAt(1, new Point2d(10.0, 0.0), 0.0, 0.0, 0.0);
                    pline.AddVertexAt(2, new Point2d(10.0, 10.0), 1.0, 0.0, 0.0);
                    pline.AddVertexAt(3, new Point2d(0.0, 10.0), 0.0, 0.0, 0.0);
                    pline.Closed = true;

                    // Dispose DBObjectCollection in case there're some objects left
                    // for which no managed wrapper have been created
                    using (DBObjectCollection plineCollection = new DBObjectCollection())
                    {
                        plineCollection.Add(pline);

                        // Dispose DBObjectCollection in case there're some objects left
                        // for which no managed wrapper have been created
                        using (DBObjectCollection regionCollection =
                            Region.CreateFromCurves(plineCollection))
                        {
                            // Always dispose an object contained in a DBObjectCollection
                            // for which a managed wrapper is created and isn't added to the database
                            using (Region region = (Region)regionCollection[0])
                            {
                                // Use Dispose to insure the new DBObject will be disposed
                                // if an exception occurs before it is added to the Database
                                using (Solid3d solid = new Solid3d())
                                {
                                    solid.Extrude(region, 30.0, 0.0);
                                    currentSpace.AppendEntity(solid);
                                    tr.AddNewlyCreatedDBObject(solid, true);
                                }
                            }
                        }
                    }
                    if ((short)Application.GetSystemVariable("DELOBJ") == 0)
                    {
                        currentSpace.AppendEntity(pline);
                        tr.AddNewlyCreatedDBObject(pline, true);
                    }
                }
                tr.Commit();
            }
        }

F#
Code: [Select]
let ExtrudePline() =
    // Never dispose Document nor Document.Editor
    let doc = AcAp.DocumentManager.MdiActiveDocument
    let ed = doc.Editor

    // Never dispose Database when the drawing is opened in the Editor
    // On the other hand, always dispose Database created with the constructor (i.e. new Database())
    let db = doc.Database
   
    // Always dispose DocumentLock
    use docLock = doc.LockDocument()

    // Always dispose Transaction
    use tr = db.TransactionManager.StartTransaction()

    // No need to dispose a DBObject opened from a transaction
    let currentSpace = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord

    // Always dispose a new DBObject which may not be added to the database
    use pline = new Polyline()
    pline.AddVertexAt(0, Point2d.Origin, 0.0, 0.0, 0.0)
    pline.AddVertexAt(1, new Point2d(10.0, 0.0), 0.0, 0.0, 0.0)
    pline.AddVertexAt(2, new Point2d(10.0, 10.0), 1.0, 0.0, 0.0)
    pline.AddVertexAt(3, new Point2d(0.0, 10.0), 0.0, 0.0, 0.0)
    pline.Closed <- true;
   
    // Dispose DBObjectCollection in case there're some objects left
    // for which no managed wrapper have been created
    use plineCollection = new DBObjectCollection()
    plineCollection.Add(pline) |> ignore

    // Dispose DBObjectCollection in case there're some objects left
    // for which no managed wrapper have been created
    use regionCollection = Region.CreateFromCurves(plineCollection)

    // Always dispose an object contained in a DBObjectCollection
    // for which a managed wrapper is created and isn't added to the database
    use region = regionCollection.[0] :?> Region

    // Use Dispose to insure the new DBObject will be disposed
    // if an exception occurs before it is added to the Database
    use solid = new Solid3d()
    solid.Extrude(region, 30.0, 0.0)
    currentSpace.AppendEntity(solid) |> ignore
    tr.AddNewlyCreatedDBObject(solid, true)

    if Application.GetSystemVariable("DELOBJ") |> unbox  = 0s then
        currentSpace.AppendEntity(pline) |> ignore
        tr.AddNewlyCreatedDBObject(pline, true)
    tr.Commit()

VB
Code: [Select]
        Public Sub ExtrudePline()
            ' Never dispose Document nor Document.Editor
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim ed As Editor = doc.Editor

            ' Never dispose Database when the drawing is opened in the Editor
            ' On the other hand, always dispose Database created with the constructor (i.e. New Database())
            Dim db As Database = doc.Database

            ' Always dispose DocumentLock
            Using doc.LockDocument()

                ' Always dispose Transaction
                Using tr As Transaction = db.TransactionManager.StartTransaction()

                    ' No need to dispose a DBObject opened from a transaction
                    Dim currentSpace As BlockTableRecord = _
                        DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)

                    ' Always dispose a new DBObject which may not be added to the database
                    Using pline As New Polyline()
                        pline.AddVertexAt(0, Point2d.Origin, 0.0, 0.0, 0.0)
                        pline.AddVertexAt(1, New Point2d(10.0, 0.0), 0.0, 0.0, 0.0)
                        pline.AddVertexAt(2, New Point2d(10.0, 10.0), 1.0, 0.0, 0.0)
                        pline.AddVertexAt(3, New Point2d(0.0, 10.0), 0.0, 0.0, 0.0)
                        pline.Closed = True

                        ' Dispose DBObjectCollection in case there're some objects left
                        ' for which no managed wrapper have been created
                        Using plineCollection As New DBObjectCollection()
                            plineCollection.Add(pline)

                            ' Dispose DBObjectCollection in case there're some objects left
                            ' for which no managed wrapper have been created
                            Using regionCollection As DBObjectCollection = _
                                Region.CreateFromCurves(plineCollection)

                                ' Always dispose an object contained in a DBObjectCollection
                                ' for which a managed wrapper is created and isn't added to the database
                                Using region As Region = DirectCast(regionCollection(0), Region)

                                    ' Use Dispose to insure the new DBObject will be disposed
                                    ' if an exception occurs before it is added to the Database
                                    Using solid As New Solid3d()
                                        solid.Extrude(region, 30.0, 0.0)
                                        currentSpace.AppendEntity(solid)
                                        tr.AddNewlyCreatedDBObject(solid, True)
                                    End Using
                                End Using
                            End Using
                        End Using
                        If CShort(Application.GetSystemVariable("DELOBJ")) = 0 Then
                            currentSpace.AppendEntity(pline)
                            tr.AddNewlyCreatedDBObject(pline, True)
                        End If
                    End Using
                    tr.Commit()
                End Using
            End Using
        End Sub

30
Layouts and printing / Plot to 3d DWF
« on: July 15, 2012, 04:23:08 PM »
Code: [Select]
using System.IO;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.PlottingServices;
 
namespace Plottings
{
    public class PlotTo3dDwf
    {
        private string dwgFile, dwfFile, dsdFile, title, outputDir;
 
        public PlotTo3dDwf()
        {
            outputDir = (string)Application.GetSystemVariable("DWGPREFIX");
            string name = (string)Application.GetSystemVariable("DWGNAME");
            dwgFile = Path.Combine(outputDir, name);
            title = Path.GetFileNameWithoutExtension(name);
            dwfFile = Path.ChangeExtension(dwgFile, "dwf");
            dsdFile = Path.ChangeExtension(dwfFile, ".dsd");
        }
 
        public PlotTo3dDwf(string outputDir)
            : this()
        {
            this.outputDir = outputDir;
        }
 
        public void Publish()
        {
            short bgPlot = (short)Application.GetSystemVariable("BACKGROUNDPLOT");
            Application.SetSystemVariable("BACKGROUNDPLOT", 0);
            try
            {
                if (!Directory.Exists(outputDir))
                    Directory.CreateDirectory(outputDir);
 
                using (DsdData dsd = new DsdData())
                using (DsdEntryCollection dsdEntries = new DsdEntryCollection())
                {
                    // add the Model layout to the entry collection
                    DsdEntry dsdEntry = new DsdEntry();
                    dsdEntry.DwgName = dwgFile;
                    dsdEntry.Layout = "Model";
                    dsdEntry.Title = title;
                    dsdEntry.Nps = "0";
                    dsdEntries.Add(dsdEntry);
                    dsd.SetDsdEntryCollection(dsdEntries);
 
                    // set DsdData
                    dsd.Dwf3dOptions.PublishWithMaterials = true;
                    dsd.Dwf3dOptions.GroupByXrefHierarchy = true;
                    dsd.SetUnrecognizedData("PwdProtectPublishedDWF", "FALSE");
                    dsd.SetUnrecognizedData("PromptForPwd", "FALSE");
                    dsd.SheetType = SheetType.SingleDwf;
                    dsd.NoOfCopies = 1;
                    dsd.ProjectPath = outputDir;
                    dsd.IsHomogeneous = true;
 
                    if (File.Exists(dsdFile))
                        File.Delete(dsdFile);
 
                    // write the DsdData file
                    dsd.WriteDsd(dsdFile);
 
                    // get the Dsd File contents
                    string str;
                    using (StreamReader sr = new StreamReader(dsdFile, Encoding.Default))
                    {
                        str = sr.ReadToEnd();
                    }
                    // edit the contents
                    str = str.Replace("Has3DDWF=0", "Has3DDWF=1");
                    str = str.Replace("PromptForDwfName=TRUE", "PromptForDwfName=FALSE");
                    // rewrite the Dsd file
                    using (StreamWriter sw = new StreamWriter(dsdFile, false, Encoding.Default))
                    {
                        sw.Write(str);
                    }
 
                    // import the Dsd file new contents in the DsdData
                    dsd.ReadDsd(dsdFile);
 
                    File.Delete(dsdFile);
 
                    PlotConfig pc = PlotConfigManager.SetCurrentConfig("DWF6 ePlot.pc3");
                    Application.Publisher.PublishExecute(dsd, pc);
                }
            }
            finally
            {
                Application.SetSystemVariable("BACKGROUNDPLOT", bgPlot);
            }
        }
    }
}

Pages: 1 [2] 3 4 ... 6