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 ... 3 4 [5] 6
61
Math and Geometry / Re: Geometry extensions
« on: February 03, 2011, 11:11:16 AM »
Hi,

Added some extension methods:

void Point2dCollection.RemoveDuplicate()
void Point2dCollection.RemoveDuplicate(Tolerance tol)
bool Point2dCollection.Contains(Point2d pt, Tolerance tol)

void Point3dCollection.RemoveDuplicate()
void Point3dCollection.RemoveDuplicate(Tolerance tol)
bool Point3dCollection.Contains(Point3d pt, Tolerance tol)

And edit the Triangle2d and Triangle3d classes:
both inherits from a 'generic' abstract class: Triangle<T> and have two new properties : CircumscribedCircle and InscribedCircle

62
This site / Re: Testing code highlighting
« on: December 15, 2010, 01:18:19 PM »
Appologies for my poor English.
I didn't want to say colorisation is a gadget in a code editor, but I think it is in a web site and according to what i saw in some other web sites (and what your saying), it seems it may not always work well: I saw some characters ('[', ']', '&', ...) displayed in html format.

Just my opinion...

63
This site / Re: Testing code highlighting
« on: December 15, 2010, 07:27:57 AM »
Hi,

IMO, there's no nedd for this kind of gadget which often provides more inconvinients than advantages.

I'd rather post/read non colorized full and right code than colorized one with syntax errors and/or restrictions.

Every one here is able to copy and paste a piece of code in its favorite code editor...

64
AutoCAD talk / LispFunction with autoCAD 2008
« on: December 06, 2010, 08:34:11 PM »
Hi,

A .NET defined LISP function (with the LispFunction attribute) can return any type of value available in LISP : string, int, double,Point3d,  SelectionSet, ObjectId (ename), TypedValue (T or nil), ResultBuffer (list)...

But it seems there's a bug with AutoCAD 2008 which only allows .NET defined LISP functions to return a ResulBuffer (a list or nil).

65
Selection sets / Selection Set Filters
« on: December 04, 2010, 10:24:53 PM »
In the .NET environment, a SelectionFilter is constructed with a TypedValue array.
A TypedValue can contain various Objects types in its Value property. The Object type is defined in the TypeCode property as an integer (or a DxfCode enum integer) which corresponds to the DXF group code of the Value.
For those who know AutoLISP, a TypedValue looks like a DXF dotted pair (even it is not the same thing, a dotted pair is a LISP specific data).
For the Values which type is String as entity type (DxfCode.Start = 0) or layer (DxfCode.Layer = 8), the Value can contain many patterns separted by commas and use wildcard patterns.
The filter can contain relational tests for the numerical values and logical grouping.

The more complete documentation in the AutoCAD Developer's Help for building sofisticated SelectionFilters is in the AutoLISP Help:
AutoLISP developer's Guide > Using the AutoLISP Language > Using AutoLISP to Manipulate AutoCAD Objects > Selection Set Handling > Selection Set Filter Lists
And the DXF group codes can be found in DXF Reference.

Here's an example to select closed polylines (lw, 2d and 3d) and closed ellipses on layers BASE and CONSTRUCTION

Code: [Select]
TypedValue[] filter =
            {   new TypedValue(-4, "<OR"),
                new TypedValue(-4, "<AND"),
                new TypedValue(0, "*POLYLINE"), // LWPOLYLINE and POLYLINE
                new TypedValue(-4, "&"),
                new TypedValue(70, 1), // Closed
                new TypedValue(-4, "<NOT"),
                new TypedValue(-4, "&"),
                new TypedValue(70, 112),  // Avoid meshes (bit codes: 16 + 32 + 64)
                new TypedValue(-4, "NOT>"),
                new TypedValue(-4, "AND>"),
                new TypedValue(-4, "<AND"),
                new TypedValue(0, "ELLIPSE"),
                new TypedValue(-4, "="),
                new TypedValue(41, 0.0), // Start parameter
                new TypedValue(-4, "="),
                new TypedValue(42, 6.283185307179586), // End parameter
                new TypedValue(-4, "AND>"),
                new TypedValue(-4, "OR>"),
                new TypedValue(8, "BASE,CONSTRUCTION")};
SelectionFilter = new SelectionFilter(filter);

target audience:{beginner}

66
Display / Zoom Objects
« on: December 04, 2010, 12:47:34 AM »
Hi,

Here's a little sample to make a Zoom on selected objects

<Edit: removed some unusefull statements>

C#
Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace ZoomObjectSample
{
    public class Zoom
    {
        [CommandMethod("ZO")]
        public void ZO()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            PromptSelectionResult psr = ed.GetSelection();
            if (psr.Status != PromptStatus.OK)
                return;
            ObjectIdCollection idCol = new ObjectIdCollection(psr.Value.GetObjectIds());
            ZoomObjects(idCol);
        }

        private void ZoomObjects(ObjectIdCollection idCol)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            using (ViewTableRecord view = ed.GetCurrentView())
            {
                Matrix3d WCS2DCS = Matrix3d.PlaneToWorld(view.ViewDirection);
                WCS2DCS = Matrix3d.Displacement(view.Target - Point3d.Origin) * WCS2DCS;
                WCS2DCS = Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) * WCS2DCS;
                WCS2DCS = WCS2DCS.Inverse();
                Entity ent = (Entity)tr.GetObject(idCol[0], OpenMode.ForRead);
                Extents3d ext = ent.GeometricExtents;
                for (int i = 1; i < idCol.Count; i++)
                {
                    ent = (Entity)tr.GetObject(idCol[i], OpenMode.ForRead);
                    Extents3d tmp = ent.GeometricExtents;
                    ext.AddExtents(tmp);
                }
                ext.TransformBy(WCS2DCS);
                view.Width = ext.MaxPoint.X - ext.MinPoint.X;
                view.Height = ext.MaxPoint.Y - ext.MinPoint.Y;
                view.CenterPoint =
                    new Point2d((ext.MaxPoint.X + ext.MinPoint.X) / 2.0, (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0);
                ed.SetCurrentView(view);
                tr.Commit();
            }
        }
    }
}

F#
Code: [Select]
module ZoomObjects

open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime

let zoomObjects (ids : ObjectId[]) =
    let doc = Application.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor
    use tr = db.TransactionManager.StartTransaction()
    use view = ed.GetCurrentView()
   
    let getEnt id = tr.GetObject(id, OpenMode.ForRead) :?> Entity
   
    let addExts (ext : Extents3d) id =
        ext.AddExtents((getEnt id).GeometricExtents)
        ext
       
    let ext = ids |> Array.fold addExts (getEnt ids.[0]).GeometricExtents
    let WCS2DCS =  Matrix3d
                    .PlaneToWorld(view.ViewDirection)
                    .PreMultiplyBy(Matrix3d.Displacement(view.Target - Point3d.Origin))
                    .PreMultiplyBy(Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target))
                    .Inverse()
    ext.TransformBy(WCS2DCS)
    view.Width <- ext.MaxPoint.X - ext.MinPoint.X
    view.Height <- ext.MaxPoint.Y - ext.MinPoint.Y
    view.CenterPoint <- new Point2d((ext.MaxPoint.X + ext.MinPoint.X) / 2.0, (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0)
    ed.SetCurrentView(view)
    tr.Commit();

[<CommandMethod("ZO")>]
let zo() =
    let ed = Application.DocumentManager.MdiActiveDocument.Editor
    let psr = ed.GetSelection()
    if psr.Status = PromptStatus.OK then
        psr.Value.GetObjectIds() |> zoomObjects

VB
Code: [Select]
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime

Namespace ZoomObjectSample
Public Class Zoom
<CommandMethod("ZO")> _
Public Sub ZO()
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim psr As PromptSelectionResult = ed.GetSelection()
If psr.Status <> PromptStatus.OK Then
Return
End If
Dim idCol As New ObjectIdCollection(psr.Value.GetObjectIds())
ZoomObjects(idCol)
End Sub

Private Sub ZoomObjects(idCol As ObjectIdCollection)
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Using tr As Transaction = db.TransactionManager.StartTransaction()
Using view As ViewTableRecord = ed.GetCurrentView()
Dim WCS2DCS As Matrix3d = Matrix3d.PlaneToWorld(view.ViewDirection)
WCS2DCS = Matrix3d.Displacement(view.Target - Point3d.Origin) * WCS2DCS
WCS2DCS = Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) * WCS2DCS
WCS2DCS = WCS2DCS.Inverse()
Dim ent As Entity = DirectCast(tr.GetObject(idCol(0), OpenMode.ForRead), Entity)
Dim ext As Extents3d = ent.GeometricExtents
For i As Integer = 1 To idCol.Count - 1
ent = DirectCast(tr.GetObject(idCol(i), OpenMode.ForRead), Entity)
Dim tmp As Extents3d = ent.GeometricExtents
ext.AddExtents(tmp)
Next
ext.TransformBy(WCS2DCS)
view.Width = ext.MaxPoint.X - ext.MinPoint.X
view.Height = ext.MaxPoint.Y - ext.MinPoint.Y
view.CenterPoint = New Point2d((ext.MaxPoint.X + ext.MinPoint.X) / 2.0, (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0)
ed.SetCurrentView(view)
tr.Commit()
End Using
End Using
End Sub
End Class
End Namespace

target audience:{intermediate}

67
This site / Re: Welcome on the AutoCAD .NET developpers forums
« on: December 03, 2010, 10:04:47 AM »
Hi Oleg,

Quote
Prog expertise: Beginner
If your prog expertise is "Beginner", what should I choose for mine ?!

Glad to see here some guys whom I learn much of my actual .NET little knowledge :clinoeil:

68
F# language / Expert F#, chapter 3
« on: November 28, 2010, 08:55:47 AM »
You can download the Chapter3 of "Expert F#" (Don Syme, Adam Granicz, Antonio Cisternino) called: "Introducing Functional Programming".

69
F# language / An Introduction to Microsoft F#
« on: November 28, 2010, 12:06:50 AM »
Another video of Luca Bolognese here which explains the basics of F# with a succulent Italian accent.


target audience:{beginner}

70
Blocks / Re: Erase doubled block references
« on: November 26, 2010, 03:06:58 PM »
As this topic became a kind of challenge at TheSwamp, you can find some other solutions there (using Linq for example).

It also appears that using List<T> seems to be much more time expansive than Dictionary<key,value> while seaching an item (even if never mind of the value).

So, in the upper code, replacing:

List<DuplicatePattern> with Dictionary<DuplicatePattern, int>

Patterns.Contains(dp) with Patterns.ContainsKey(db)

Patterns.Add(dp) with Patterns.Add(dp, 0)

should increase the execution speed.

71
Blocks / Re: Erase doubled block references
« on: November 25, 2010, 01:44:33 PM »
Sorry, no need to use a ResultBuffer and it seems to be faster using a SelectionSet

Here's a new way:
Code: [Select]
        struct DuplicatePattern
        {
            public string Name;
            public string Layer;
            public ObjectId OwnerId;
            public double PositionX;
            public double PositionY;
            public double PositionZ;
            public double Rotation;
            public double ScaleX;
            public double ScaleY;
            public double ScaleZ;
        }

        private int DeleteDuplicatedBlockRef()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            int result = 0;
            SelectionFilter filter = new SelectionFilter(new TypedValue[1] { new TypedValue(0, "INSERT") });
            PromptSelectionResult psr = ed.SelectAll(filter);
            if (psr.Status != PromptStatus.OK)
                return 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                List<DuplicatePattern> Patterns = new List<DuplicatePattern>();
                foreach (ObjectId id in psr.Value.GetObjectIds())
                {
                    BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead, false);
                    DuplicatePattern dp = new DuplicatePattern();
                    dp.OwnerId = br.OwnerId;
                    dp.Name = br.Name;
                    dp.Layer = br.Layer;
                    dp.PositionX = Math.Round(br.Position.X, 6);
                    dp.PositionY = Math.Round(br.Position.Y, 6);
                    dp.PositionZ = Math.Round(br.Position.Z, 6);
                    dp.Rotation = Math.Round(br.Rotation, 6);
                    dp.ScaleX = Math.Round(br.ScaleFactors.X, 6);
                    dp.ScaleY = Math.Round(br.ScaleFactors.Y, 6);
                    dp.ScaleZ = Math.Round(br.ScaleFactors.Z, 6);
                    if (Patterns.Contains(dp))
                    {
                        br.UpgradeOpen();
                        br.Erase();
                        result++;
                    }
                    else
                        Patterns.Add(dp);
                }
                tr.Commit();
            }
            return result;
        }

72
Blocks / Re: Erase doubled block references
« on: November 24, 2010, 08:32:38 PM »
With the hel of kaefer (@TheSwamp), I learned some functions of the F# Seq module (IEnumerable) which made me able to rewrite a more concise and faster routine.

Code: [Select]
let duplicate (b: BlockReference) =
    b.Name,
    b.OwnerId,
    Math.Round(b.Position.X, 6),
    Math.Round(b.Position.Y, 6),
    Math.Round(b.Position.Z, 6),
    b.Layer,
    Math.Round(b.Rotation, 6),
    Math.Round(b.ScaleFactors.X, 6),
    Math.Round(b.ScaleFactors.Y, 6),
    Math.Round(b.ScaleFactors.Z, 6) 

let deleteDuplicatedBlockRef() =
    let db = HostApplicationServices.WorkingDatabase
    use tr = db.TransactionManager.StartTransaction()

    let getRefs btrId =
        let btr = tr.GetObject(btrId, OpenMode.ForRead) :?> BlockTableRecord
        btr.GetBlockReferenceIds(true, false)
        |> Seq.cast<_>
       
    let openRefs brefId =
        tr.GetObject(brefId, OpenMode.ForRead) :?> BlockReference
       
    let cnt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
              |> Seq.cast<_>
              |> Seq.collect getRefs
              |> Seq.map openRefs
              |> Seq.groupBy duplicate
              |> Seq.collect (fun x -> snd x |> Seq.skip 1)
              |> Seq.fold (fun cnt bref ->
                            bref.UpgradeOpen()
                            bref.Erase()
                            cnt + 1 ) 0
    tr.Commit()
    cnt

73
Layouts and printing / Re: Get the current layout
« on: November 24, 2010, 05:16:16 PM »
As far as I know, while using a 'Using' statement on an object, you don't need to explicitly call dispose. The object should be automatically disposed at the end of the code block  or if an exception is thrown.

With a transaction, all the objects opened with Transaction.GetObject() and the new ones added to the transaction with AddNewlyCreatedDBObject() should be automatically disposed too.
But if an error occurs before 'new' objects are added to the database, they won't be disposed.

If an exception occurs before the transactions is committed, the Dispose() is called by 'Using' and all changes made to database within this transaction are rolled back.

So, in my opinion, the F_GetCurrentLayout method should be like this (no need to Commit the transaction while there were no changes to the Database):
Code: [Select]
Public Function F_GetCurrentLayout() As Layout
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim lm As LayoutManager = LayoutManager.Current
Using tr As Transaction = db.TransactionManager.StartTransaction()
Return DirectCast(tr.GetObject(lm.GetLayoutId(lm.CurrentLayout), OpenMode.ForRead), Layout)
End Using
End Function

To learn more about when and what disposing, you can have a look to this video

74
Blocks / Re: Erase doubled block references
« on: November 24, 2010, 02:54:52 PM »
I think I got something working with the strcture way using a ResultBuffer (the AutoCAD .NET/ObjectARX object which looks the most like a LISP DXF list).

In the following example:
The ParamBlockDoubled are stored in a List<ParamBlockDoubled>, there's no need to use a Dictionary as the items Value (objectId) are never used.
DoubleToErase is defined as a List<BlockReference> because it avoid to open them twice from their ObjectId.
It still uses the BlockTable -> BlockTableRecord _> GetReferenceIds route which avoid to run through the whole database.

Code: [Select]
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace DuplicateTest
{
    public class Commands
    {
        [CommandMethod("Test")]
        public void DelDupBlkRef()
        {
            try
            {
                int del = DeleteDuplicatedBlockRef();
                Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased");
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog("\nError: " + e.Message);
            }
        }

        private int DeleteDuplicatedBlockRef()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            int result = 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                List<ParamBlockDoubled> CollWithoutDouble = new List<ParamBlockDoubled>();
                List<BlockReference> DoubleToErase = new List<BlockReference>();
                foreach (ObjectId id in bt)
                {
                    BlockTableRecord btr =
                        (BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite);
                    ObjectIdCollection idCol = btr.GetBlockReferenceIds(true, false);
                    foreach (ObjectId oId in idCol)
                    {
                        BlockReference br = (BlockReference)tr.GetObject(oId, OpenMode.ForRead, false);
                        ParamBlockDoubled pbd = new ParamBlockDoubled(br);
                        if (!CollWithoutDouble.Contains(pbd))
                            CollWithoutDouble.Add(pbd);
                        else
                            DoubleToErase.Add(br);
                    }
                }
                foreach (BlockReference b in DoubleToErase)
                {
                    b.UpgradeOpen();
                    b.Erase();
                    result ++;
                }
                tr.Commit();
            }
            return result;
        }

        public struct ParamBlockDoubled
        {
            // fields
            public ResultBuffer resBuf;

            // constructor
            public ParamBlockDoubled(BlockReference bRef)
            {
                Point3d pos = new Point3d(
                    Math.Round(bRef.Position.X, 6),
                    Math.Round(bRef.Position.Y, 6),
                    Math.Round(bRef.Position.Z, 6));
                resBuf =
                    new ResultBuffer(
                        new TypedValue[8] {
                            new TypedValue(330, bRef.OwnerId),
                            new TypedValue(2, bRef.Name),
                            new TypedValue(10, pos),
                            new TypedValue(8, bRef.Layer),
                            new TypedValue(50, Math.Round(bRef.Rotation, 6)),
                            new TypedValue(40, Math.Round(bRef.ScaleFactors.X, 6)),
                            new TypedValue(41, Math.Round(bRef.ScaleFactors.Y, 6)),
                            new TypedValue(42, Math.Round(bRef.ScaleFactors.Z, 6))});
            }

            // override method
            public override bool Equals(object obj)
            {
                if (obj.GetType() != typeof(ParamBlockDoubled))
                    return false;
                ParamBlockDoubled pbd = (ParamBlockDoubled)obj;
                return this.resBuf.Equals(pbd.resBuf);
            }

            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }
    }
}

75
Blocks / Re: Erase doubled block references
« on: November 24, 2010, 01:02:33 PM »
1_ Extension methods is a way to add methods to an already existing class. Usually they're compiled in a separate dll so that while this dll is refered by another project, these methods are available the same way as built-in methods.
In the upper example, a 'Duplicate' method is added to the BlockReference class, it's visible in the intellisense as:
Bool BlockReference.Duplicate(BlockReference br).
But as I said, you can define a private method inside your class: Bool Duplicate(BlockReference br1, BlockReference br2).

2_ I really think the structure/GetHashCode... way isn't the simpler one because you have to compare objects with different types (String, Point3d, Double, ...) with tolerances. This way is easy using LISP which allows to build list of different type objects.
The 'for' statement used in the upper example is a classical way to run through collections. It's optimised here by removing the duplicated items from the collection at each loop.

3_ As all functional programming languages, F# provides specific higher order functions to deal with collections (List, Array, Seq) which have none equivalent ones in VB or C#.

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