Jump to content

Recommended Posts

Bonjours,

Alors voila j'ai un petit soucis que je n'ai toujours pas réussi a résoudre,j'explique :

 

J'ai en entré N polyligne fermée.

Ces polylignes s'intersectent.

Ce que je voudrais,c'est un algo qui a partir de deux polylignes en entré retourne une seule polyligne en sortie.

Le must serait de ne travailler qu'avec un nuage de point,mais malgrès mes recherches et l'élaboration d'un algo basé sur Graham'scan je ne suis pas parvenue a grand chose ...

 

Au jour d'aujourd'hui,je me débrouille comme je peux en passant par des régions et des opérations booléeennes, mais ce n'est pas le top.Des problèmes peuvent survenir à la suite de bug autocad ( exemple;après l'union de deux régions autocad peux nous sortir une région résultante qui n'est pas planaire!! ) et qui rendent la fonction explode non fonctionnelle.Du moment où cette région résultante n'est plus planaire,toutes les opérations booléenne derrière donneront une région résultante pourrie.

 

Dans la continuité de la problématique précédente ( un algo qui me donnerait le meme résultat qu'avec les régions ) j'ai un autre problème mais cette fois ci avec des hachure :

 

Grosso,l'utilisateur dessine une polyligne dans laquelle vont se trouver des parcelles ( polyligne ).

Une fois que l'utilisateur a terminé le tracé de la polyligne,je récupère le contenu et hachure la zone.Puis via une petite interface il peux décocher les zones a ne pas hachurer ... là ou je coince,c'est lorsque la hachure a créer possède deux boucles externe on va dire ... en fonction de la géométrie,autocad me rajoute des points a mon contour,et je me retrouve avec des segments de longueur 0 .... derrière la hachure merde et ne prends pas en compte le contour incriminé.

 

 

Pour terminerai par,merci à ceux qui vont prendre le temps de lire mon pavé,je bosse en VB.NET sur autocad 2009 et que je suis ouvert a répondre a toutes questions.

 

Cordialement,

 

PS: image explicative du premier problème

http://www.hebergeur-images.fr/images/1250423745.jpg

 

[Edité le 15/4/2011 par bazoul]

Link to post
Share on other sites

Salut,

 

 

Je ne suis pas sûr de comprendre la demande (je ne vois pas l'image) mais s'il s'agit de faire une "enveloppe convexe" (convex hull) à partir d'un nuage de points (Graham's scan), je te propose ces codes :

 

 

EDIT : ajout d'un facteur de tolérance dans la comparaison des cosinus lors du tri de la liste (problème avec les points colinéaires dans certains cas)

 

 

C#

 

using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace ConvexHull
{
   public class Commands
   {
       private Point2d _p0;

       private 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-9;
       }

       private int ComparePoints(Point2d p1, Point2d p2)
       {
           if (p1.IsEqualTo(p2)) return 0;
           double d1 = _p0.GetDistanceTo(p1);
           double d2 = _p0.GetDistanceTo(p2);
           if (d1 == 0.0) return -1;
           if (d2 == 0.0) return 1;
           double cos = (p2.X - _p0.X) / d2 - (p1.X - _p0.X) / d1;
           if (cos < -1e-9) return -1;
           if (cos > 1e-9) return 1;
           return d1.CompareTo(d2);
       }

       private List<Point2d> ConvexHull(List<Point2d> pts)
       {
           _p0 = pts[0];
           for (int i = 1; i < pts.Count; i++)
           {
               Point2d pt = pts[i];
               if (pt.Y < _p0.Y || (pt.Y == _p0.Y && pt.X < _p0.X))
                   _p0 = pt;
           }
           pts.Remove(_p0);
           pts.Sort(ComparePoints);
           pts.Insert(0, _p0);
           for (int i = 1; i < pts.Count - 1; i++)
           {
               while (i > 0 && Clockwise(pts[i - 1], pts[i], pts[i + 1]))
               {
                   pts.RemoveAt(i);
                   i--;
               }
           }
           return pts;
       }

       [CommandMethod("ch", CommandFlags.UsePickSet)]
       public void testCh()
       {
           Document doc = AcAp.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;
           TypedValue[] filter = new TypedValue[1] { new TypedValue(0, "POINT") };
           PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
           if (psr.Status != PromptStatus.OK) return;
           using (Transaction tr = db.TransactionManager.StartTransaction())
           using (Polyline pline = new Polyline())
           {
               List<Point2d> pts = new List<Point2d>();
               foreach (SelectedObject so in psr.Value)
               {
                   DBPoint dbPt = (DBPoint)tr.GetObject(so.ObjectId, OpenMode.ForRead);
                   pts.Add(new Point2d(dbPt.Position.X, dbPt.Position.Y));
               }
               for (int i = 0; i < ConvexHull(pts).Count; i++)
               {
                   pline.AddVertexAt(i, pts[i], 0.0, 0.0, 0.0);
               }
               pline.Closed = true;
               pline.SetDatabaseDefaults();
               BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
               btr.AppendEntity(pline);
               tr.AddNewlyCreatedDBObject(pline, true);
               tr.Commit();
           }
       }
   }
}

 

 

ou F#

 

module ConvexHull

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

type AcAp = Autodesk.AutoCAD.ApplicationServices.Application

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
   
let convexHull (pts : Point2d seq) = 
   let rec fill acc pt =
       match acc with
       | a :: b :: _ when clockwise b a pt -> fill acc.Tail pt
       | _ -> pt :: acc
   let p0 = pts 
            |> Seq.reduce (fun p1 p2 -> 
               if p2.Y < p1.Y || (p1.Y = p2.Y && p2.X < p1.X) then p2 else p1)
   pts 
   |> List.ofSeq
   |> List.sortBy (fun p ->
       let d = p0.GetDistanceTo(p)
       (Math.Round((p0.X - p.X) / d, 8), d))
   |> List.fold fill []
   |> List.rev

[<CommandMethod("ch")>]
let Test() =
   let doc = AcAp.DocumentManager.MdiActiveDocument
   let db = doc.Database
   let ed = doc.Editor
   let psr = ed.GetSelection(new SelectionFilter([| new TypedValue(0, "POINT") |]))
   if psr.Status = PromptStatus.OK then
       use tr = db.TransactionManager.StartTransaction()
       use pl = new Polyline()
       psr.Value
       |> Seq.cast<_>
       |> Seq.map (fun (so : SelectedObject) -> 
           let pt = tr.GetObject(so.ObjectId, OpenMode.ForRead) :?> DBPoint
           new Point2d(pt.Position.X, pt.Position.Y))
       |> convexHull
       |> List.fold(fun i p ->  pl.AddVertexAt(i, p, 0.0, 0.0, 0.0); i + 1) 0
       |> ignore
       pl.Closed <- true
       pl.SetDatabaseDefaults()
       let btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) :?> BlockTableRecord
       btr.AppendEntity(pl) |> ignore
       tr.AddNewlyCreatedDBObject(pl, true) 
       tr.Commit()

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Link to post
Share on other sites

Je te remercie giles pour ce code,ça ne réponds pas a mon besoin mais je te remercie de la peine que tu t'es donné.

 

J'étais a l'origine partie de graham'scan pour obtenir l'enveloppe convexe.Puis de cette enveloppe convexe j'intégré une partie des points du contour des polyligne de départ au contour final.

Cela fonctionnait pas mal,mais j'étais bloqué au moment ou il fallait trouver le meilleure point de raccord diront nous entre les deux polylignes de départ ...

 

En fait,mon besoin c'est un algorythme de calcul d'enveloppe concave,et non convexe ... et les concavité,c'est la que ça coince !

 

PS: je vois que tu tattes un peu le F#,quel est l'interet de faire du F# plutot que du vb.net ( que je pratique ,ou encore du C# que j'aimerais bien pratiquer mais que je n'ai pas le temps de le faire sur mon lieux de travail! )

 

PPS: d'ailleurs en regardant un peu la syntaxe du F# j'ai l'impression de voir un peu du vba notament avec les 'let' qui je pense était les 'set' en vba pour affectuer une variable de type objet ...

 

[Edité le 15/4/2011 par bazoul]

Link to post
Share on other sites

Salut,

 

quel est l'interet de faire du F#

Par rapport à VB. ou C# (qui sont semblables), F# apporte, en plus, la possibilité de faire de la programmation fonctionnelle (en ça F# est beaucoup plus proche du LISP que du VBA) et des bibliothèques spécifiques, voir ici.

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Link to post
Share on other sites

Re,

 

 

Pour ton problème, j'avais fait un truc en LISP (Fusion sur cette page) mais qui utilise les régions (d'ailleurs, je n'ai jamais eu de soucis avec ni eu de retour négatif).

 

 

Si tu ne veux pas passer par les régions, une façon serait de :

 

- calculer l'aire algébrique des polylignes, si elle est négative, en inverse le sens pour avoir toutes les polylignes dans le même sens

 

- trouver les points d'intersection des polylignes

 

- à partir du premier sommet d'une polyligne récupérer tous les sommets jusqu'à une intersection et continuer à partir du paramètre à ce point d'intersection sur l'autre polyligne jusqu'au prochain point d'intersection où on change à nouveau de polyligne...

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Link to post
Share on other sites

Oui giles,j'étais parti sur cette solution au départ.

Sa marche niquel du moment que tu n'a pas de boucle interne.

 

A partir du moment ou ya une boucle interne sa se complique.Ou alors a partir du moment ou les deux contour de polyligne se coupent en formant du coup des contour indépendant ...

Vaste problème que celui de la création de région.

J'ai cherché un algorythme permettant de me dégager des régions pour bosser directement avec des points,sans succès réel ( a savoir,sa ne marche que dans les cas simple! )

 

Concernant mes soucis de région,je suis sur autocad 2009,le problème en question a peut etre été corrigé dans les versions ultérieures ... mais je peux te garantir qu'en créant une région avec une liste de point2D,on peut obtenir des régions bizaroides ...

 

Link to post
Share on other sites
mais je peux te garantir qu'en créant une région avec une liste de point2D,on peut obtenir des régions bizaroides ...

 

 

Pourquoi utiliser des points, la méthode statique (shared en VB) Region.CreateFromCurves permet de créer une région à partir d'une collection de lignes et arcs.

 

 

J'ai essayer de transposer ce que j'avais écrit en LISP en C#, ça semble marcher (les polylignes sélectionnées doivent être dans le même plan même s'il est différent du plan du SCG).

 

 

http://gile.pagesperso-orange.fr/MergePlines.gif

 

 

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;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace MergePlines
{
   public class Commands
   {
       Point2d _pt;
       Document _doc = AcAp.DocumentManager.MdiActiveDocument;

       private bool PointPredicate(Point2d p)
       {
           return _pt.IsEqualTo(p);
       }

       private void Dispose(DBObjectCollection col)
       {
           for (int i = 0; i < col.Count; i++)
           {
               col[i].Dispose();
           }
       }

       private void MergePlines(ObjectId[] ids)
       {
           Database db = _doc.Database;
           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               DBObjectCollection segments = new DBObjectCollection();
               BlockTableRecord btr =
                   (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
               Polyline pl = (Polyline)tr.GetObject(ids[0], OpenMode.ForWrite);
               Vector3d normal = pl.Normal;
               double elev = pl.Elevation;
               pl.Explode(segments);
               pl.Erase();
               Plane plane = new Plane(Point3d.Origin, normal);
               for (int i = 1; i < ids.Length; i++)
               {
                   pl = (Polyline)tr.GetObject(ids[i], OpenMode.ForWrite);
                   if (pl.Elevation == elev && pl.Normal.IsEqualTo(normal))
                   {
                       pl.Explode(segments);
                       pl.Erase();
                   }
               }
               DBObjectCollection regions = Region.CreateFromCurves(segments);
               Region reg = (Region)regions[0];
               for (int i = 1; i < regions.Count; i++)
               {
                   reg.BooleanOperation(BooleanOperationType.BoolUnite, (Region)regions[i]);
                   regions[i].Dispose();
               }
               segments.Clear();
               Dispose(segments);
               reg.Explode(segments);
               reg.Dispose();
               List<Point2d> starts = new List<Point2d>();
               List<Point2d> ends = new List<Point2d>();
               List<double> bulges = new List<double>();
               for (int i = 0; i < segments.Count; i++)
               {
                   if (segments[i] is Region)
                   {
                       ((Region)segments[i]).Explode(segments);
                       continue;
                   }
                   Curve crv = (Curve)segments[i];
                   Point3d start = crv.StartPoint;
                   Point3d end = crv.EndPoint;
                   double bulge = 0.0;
                   if (crv is Arc)
                   {
                       Arc arc = (Arc)crv;
                       double angle = arc.Center.GetVectorTo(start).GetAngleTo(arc.Center.GetVectorTo(end), arc.Normal);
                       bulge = Math.Tan(angle / 4.0);
                   }
                   starts.Add(start.Convert2d(plane));
                   ends.Add(end.Convert2d(plane));
                   bulges.Add(bulge);
               }
               Dispose(segments);
               while (starts.Count > 0)
               {
                   using (Polyline pline = new Polyline())
                   {
                       pline.AddVertexAt(0, starts[0], bulges[0], 0.0, 0.0);
                       pline.AddVertexAt(1, ends[0], 0.0, 0.0, 0.0);
                       _pt = ends[0];
                       starts.RemoveAt(0);
                       ends.RemoveAt(0);
                       bulges.RemoveAt(0);
                       int i = 2;
                       while (starts.Contains(_pt) || ends.Contains(_pt))
                       {
                           int index = starts.FindIndex(PointPredicate);
                           if (index > -1)
                           {
                               _pt = ends[index];
                               pline.AddVertexAt(i, _pt, 0.0, 0.0, 0.0);
                               pline.SetBulgeAt(i - 1, bulges[index]);
                           }
                           else
                           {
                               index = ends.FindIndex(PointPredicate);
                               _pt = starts[index];
                               pline.AddVertexAt(i, _pt, 0.0, 0.0, 0.0);
                               pline.SetBulgeAt(i - 1, -bulges[index]);
                           }
                           starts.RemoveAt(index);
                           ends.RemoveAt(index);
                           bulges.RemoveAt(index);
                           i++;
                       }
                       pline.RemoveVertexAt(pline.NumberOfVertices - 1);
                       pline.SetDatabaseDefaults();
                       pline.Closed = true;
                       pline.Normal = normal;
                       pline.Elevation = elev;
                       btr.AppendEntity(pline);
                       tr.AddNewlyCreatedDBObject(pline, true);
                   }
               }
               tr.Commit();
           }
       }

       [CommandMethod("Test")]
       public void Test()
       {
           Editor ed = _doc.Editor;
           TypedValue[] filter = new TypedValue[3]{
               new TypedValue(0, "LWPOLYLINE"),
               new TypedValue(-4, "&"),
               new TypedValue(70, 1)};
           PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
           if (psr.Status == PromptStatus.OK)
           {
               try
               {
                   MergePlines(psr.Value.GetObjectIds());
               }
               catch (Autodesk.AutoCAD.Runtime.Exception e)
               {
                   ed.WriteMessage("\nErreur: " + e.Message);
               }
           }
       }
   }
}

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Link to post
Share on other sites

Je vais tester ton approche ..

en revanche,pour l'explosion de la région je te conseillerai plutot le code suivant ( désolé je ne suis pas expert C#,ce sera du vb ... )

 

 

       Dim sbep As SubentityId
       Dim ids As ObjectId()
       Dim OutsidePath As FullSubentityPath
       Dim lenti As Entity
       Dim CurrentRegion As Region
       Dim comptent As Integer = 1
       Dim EntitiesInRegionToConvert As New DBObjectCollection
       Dim EntitiesFromExplodeRegion As New DBObjectCollection

  'On commence a 1 sinon on obtient systématiquement Nothing a la position 0
               While True
                   Try
                       ids = New ObjectId(0) {}
                       'indiquer le type de l'entité que l'on souhaite récupérer
                       sbep = New SubentityId(SubentityType.Face, comptent)
                       OutsidePath = New FullSubentityPath(ids, sbep)
                       'Récupérer l'entité au conpteur indiquer
                       lenti = RegionToConvert.GetSubentity(OutsidePath)
                       'si on obtient Nothing c'est qu'on a plus rien a récupérer,donc on sort du while pour reprendre le cours
                       'normal du traitement
                       If lenti Is Nothing Then Exit While
                       EntitiesInRegionToConvert.Add(lenti)
                   Catch
                       tr.Dispose() : tr = Nothing
                       Return False
                   End Try
                   comptent += 1

               End While

                   For i As Integer = 0 To EntitiesInRegionToConvert.Count - 1
                       System.Windows.Forms.Application.DoEvents()
                       'Récupétation de la région courante
                       CurrentRegion = CType(EntitiesInRegionToConvert.Item(i), Region)
                       While True
                           Try
                               ids = New ObjectId(0) {}
                               'indiquer le type de l'entité que l'on souhaite récupérer
                               sbep = New SubentityId(SubentityType.Edge, comptent)
                               OutsidePath = New FullSubentityPath(ids, sbep)
                               'Récupérer l'entité au conpteur indiquer
                               lenti = CurrentRegion.GetSubentity(OutsidePath)
                               'si on obtient Nothing c'est qu'on a plus rien a récupérer,donc on sort du while pour reprendre le cours
                               'normal du traitement
                               If lenti Is Nothing Then Exit While
                               EntitiesFromExplodeRegion.Add(lenti)
                           Catch
                               tr.Dispose() : tr = Nothing
                               Return False
                           End Try
                           comptent += 1

                       End While
                       CurrentRegion.Dispose() : CurrentRegion = Nothing
                   Next i
                   EntitiesInRegionToConvert.Dispose() : EntitiesInRegionToConvert = Nothing

 

Code testé et fonctionnel là ou d'autre pouvais produire des erreurs notament sur autocad 2009 ...

 

Link to post
Share on other sites

Merci pour la recommandation, mais je ne rencontre aucun problème avec Entity.Explode() (testé sur A2007, A2010 et A2011).

 

 

J'en ai profité pour finaliser un commande qui fonctionne que que soient les plans de construction de polylignes sélectionnées.

 

http://www.theswamp.org/index.php?topic=37976.msg429899#msg429899

 

 

La DLL : MergePlines.zip

 

 

Le code :

 

using System;
using System.Collections.Generic;
using System.Globalization;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace MergePlines
{
   public class Commands
   {
       bool _en;
       Point2d _pt;
       Document _doc;

       public Commands()
       {
           //System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
           //System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
           _en = CultureInfo.CurrentCulture.Name.StartsWith("en-");
           _doc = AcAp.DocumentManager.MdiActiveDocument;
       }

       private bool PointPredicate(Point2d p)
       {
           return _pt.IsEqualTo(p);
       }

       private void DisposeAll(DBObjectCollection col)
       {
           for (int i = 0; i < col.Count; i++)
           {
               col[i].Dispose();
           }
       }

       private int MergePlines(ObjectIdCollection ids, bool erase)
       {
           Database db = _doc.Database;
           int result = 0;
           using (Transaction tr = db.TransactionManager.StartTransaction())
           using (DBObjectCollection segments = new DBObjectCollection())
           {
               BlockTableRecord btr =
                   (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
               List<Point2d> starts = new List<Point2d>();
               List<Point2d> ends = new List<Point2d>();
               List<double> bulges = new List<double>();
               List<Polyline> plines = new List<Polyline>();
               Polyline pl;
               while (ids.Count > 0)
               {
                   segments.Clear();
                   starts.Clear();
                   ends.Clear();
                   bulges.Clear();
                   plines.Clear();
                   pl = (Polyline)tr.GetObject(ids[0], OpenMode.ForWrite);
                   Vector3d normal = pl.Normal;
                   double elev = pl.Elevation;
                   Plane plane = new Plane(Point3d.Origin, normal);
                   plines.Add(pl);
                   ids.RemoveAt(0);
                   for (int i = 0; i < ids.Count; )
                   {
                       pl = (Polyline)tr.GetObject(ids[i], OpenMode.ForWrite);
                       if (Math.Abs(pl.Elevation - elev) < 1e-12 && pl.Normal.IsEqualTo(normal))
                       {
                           plines.Add(pl);
                           ids.RemoveAt(i);
                       }
                       else
                           i++;
                   }
                   if (plines.Count < 2)
                       continue;
                   for (int i = 0; i < plines.Count; i++)
                   {
                       pl = plines[i];
                       pl.Explode(segments);
                       if (erase) pl.Erase();
                   }
                   using (DBObjectCollection regions = Region.CreateFromCurves(segments))
                   {
                       Region reg = (Region)regions[0];
                       for (int i = 1; i < regions.Count; i++)
                       {
                           reg.BooleanOperation(BooleanOperationType.BoolUnite, (Region)regions[i]);
                           regions[i].Dispose();
                       }
                       DisposeAll(segments);
                       segments.Clear();
                       reg.Explode(segments);
                       reg.Dispose();
                       for (int i = 0; i < segments.Count; i++)
                       {
                           if (segments[i] is Region)
                           {
                               ((Region)segments[i]).Explode(segments);
                               continue;
                           }
                           Curve crv = (Curve)segments[i];
                           Point3d start = crv.StartPoint;
                           Point3d end = crv.EndPoint;
                           double bulge = 0.0;
                           if (crv is Arc)
                           {
                               Arc arc = (Arc)crv;
                               double angle = arc.Center.GetVectorTo(start).GetAngleTo(arc.Center.GetVectorTo(end), arc.Normal);
                               bulge = Math.Tan(angle / 4.0);
                           }
                           starts.Add(start.Convert2d(plane));
                           ends.Add(end.Convert2d(plane));
                           bulges.Add(bulge);
                       }
                       DisposeAll(segments);
                       while (starts.Count > 0)
                       {
                           using (Polyline pline = new Polyline())
                           {
                               pline.AddVertexAt(0, starts[0], bulges[0], 0.0, 0.0);
                               pline.AddVertexAt(1, ends[0], 0.0, 0.0, 0.0);
                               _pt = ends[0];
                               starts.RemoveAt(0);
                               ends.RemoveAt(0);
                               bulges.RemoveAt(0);
                               int i = 2;
                               while (starts.Contains(_pt) || ends.Contains(_pt))
                               {
                                   int index = starts.FindIndex(PointPredicate);
                                   if (index > -1)
                                   {
                                       _pt = ends[index];
                                       pline.AddVertexAt(i, _pt, 0.0, 0.0, 0.0);
                                       pline.SetBulgeAt(i - 1, bulges[index]);
                                   }
                                   else
                                   {
                                       index = ends.FindIndex(PointPredicate);
                                       _pt = starts[index];
                                       pline.AddVertexAt(i, _pt, 0.0, 0.0, 0.0);
                                       pline.SetBulgeAt(i - 1, -bulges[index]);
                                   }
                                   starts.RemoveAt(index);
                                   ends.RemoveAt(index);
                                   bulges.RemoveAt(index);
                                   i++;
                               }
                               pline.RemoveVertexAt(pline.NumberOfVertices - 1);
                               pline.SetDatabaseDefaults();
                               pline.Closed = true;
                               pline.Normal = normal;
                               pline.Elevation = elev;
                               btr.AppendEntity(pline);
                               tr.AddNewlyCreatedDBObject(pline, true);
                               result++;
                           }
                       }
                   }
               }
               tr.Commit();
           }
           return result;
       }

       [CommandMethod("UPL", CommandFlags.UsePickSet)]
       public void UnionPlines()
       {
           Editor ed = _doc.Editor;
           TypedValue[] filter = new TypedValue[3]{
               new TypedValue(0, "LWPOLYLINE"),
               new TypedValue(-4, "&"),
               new TypedValue(70, 1)};
           PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
           if (psr.Status != PromptStatus.OK)
               return;
           PromptKeywordOptions pko = new PromptKeywordOptions("\nEffacer les polylignes source ?: ");
           if (_en)
           {
               pko.Message = "\nErase source polylines ?: ";
               pko.Keywords.Add("Yes");
               pko.Keywords.Add("No");
               pko.Keywords.Default = "Yes";
           }
           else
           {
               pko.Keywords.Add("Oui");
               pko.Keywords.Add("Non");
               pko.Keywords.Default = "Oui";
           }
           pko.AllowNone = true;
           PromptResult pr = ed.GetKeywords(pko);
           if (pr.Status == PromptStatus.Cancel)
               return;
           bool erase = _en ? pr.StringResult == "Yes" : pr.StringResult == "Oui";
           try
           {
               ObjectIdCollection ids = new ObjectIdCollection(psr.Value.GetObjectIds());
               int n = MergePlines(ids, erase);
               if (_en)
                   ed.WriteMessage("\n{0} polyline{1} have been created", n, n > 1 ? "s" : "");
               else
                   ed.WriteMessage("\n{0} polyligne{1} créée{1}", n, n > 1 ? "s" : "");
           }
           catch (Autodesk.AutoCAD.Runtime.Exception e)
           {
               ed.WriteMessage("\n{0}: {1}", _en ? "Error" : "Erreur", e.Message);
           }
       }
   }
}

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Link to post
Share on other sites

 

Hello Gilles

 

Super ta nouvelle routine de fusion des polylignes - Merci ! :)

Je viens de la tester sur MAP 2008 et 2010 32 bits

 

Sauf que il faudrait peut etre redire que :

- Chargement de ta super DLL par NETLOAD

- Lancement par UPL (pour Union PLines)

 

J'ai un test encore plus complique que le tien

et dans une 2eme etape j'en fais un joli MPOLYGON :cool:

 

Encore Merci, Le Decapode

 

Autodesk Expert Elite Team

Link to post
Share on other sites

 

Hello Gilles

 

Eh c quoi alors les avantages / inconvenient de ces 2 routines !?

 

UPL (Mergeplines) est-il plus rapide ?

 

Et sinon une autre question : la fiabilite de 2 methodes !?

 

Le Decapode (Unioniste de PolyLignes)

 

Autodesk Expert Elite Team

Link to post
Share on other sites

Eh c quoi alors les avantages / inconvenient de ces 2 routines !?

Elles font la même choses, donc les avantages/inconvénients sont ceux de LISP par rapport à .NET : LISP est plus facile à charger, maintenir, modifier, .NET est (peut-être, voir ci-dessous) un peu plus rapide à l'exécution.

C'est ce sujet qui m'a amené à traduire en .NET le LISP Fusion. En transcrivant le code je l'ai amélioré (pour qu'il traite les polylignes coplanaires par groupe), j'ai ensuite ajouté cette amélioration aux (vieux) LISP Fusion.

 

UPL (Mergeplines) est-il plus rapide ?

Théoriquement les programmes .NET (compilés) s'exécutent plus vite que les programmes LISP (interprétés). Sans avoir testé, je pense que dans ce cas, la différence devrait être relativement insensible, le processus le plus "couteux" étant la création de regions qui, dans les deux cas utilise le modeleur. La différence pourrait se faire sur les tris des polylignes et les différentes boucles et ne serait donc notable qu'avec de grandes quantité de polylignes à traiter.

 

Et sinon une autre question : la fiabilite de 2 methodes !?

Difficile à dire pour l'instant, c'est tout neuf et demanderait plus de test, mais il ne devrait pas y avoir de différence de fiabilité entre les deux méthode.

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Link to post
Share on other sites

Bonjour Gile,

J'ai téléchargé MergePlines et PolylineEdit_English (PolylineEdit.dll) la fonction netload les charge bien mais pour une j'ai essayé UPL mais la ligne de commande reste à Commande inconnue et pareil pour l'autre j'ai essayé tous les noms possibles mais pas de lancement de MergePlines et de PolylineEdit.

 

Le tout sur AutoCAD MAP 3D 2009.

 

Cordialement,

 

Fabcad

Link to post
Share on other sites

Salut,

 

Pour MergePlines.zip, j'ai effectivement cafouillé, j'avais renommé la commande pour faire des test comparatifs*.

Le nouveau lien pointe bien sur la bonne DLL avec la commande nommée : UPL

Pour PolylineEdit, si tu as bien téléchargé le ZIP depuis ce sujet, les commandes sont : AVX et DVX.

 

* J'ai finalement fait quelques test de vélocité les versions .NET (C# ou F#) sont environ 2.5 fois plus rapides que la version LISP (Fusion).

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Link to post
Share on other sites

Merci Gile pour les informations, c'est génial comme d'habitude.

 

Pour info : PlineEdit.dll fonctionne à merveille et en plus cerise sur le gâteau, elle conserve les données d'objets.

 

Encore merci.

 

A+

 

[Edité le 22/4/2011 par fabcad]

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...