Aller au contenu

Creer un Arc tangent à deux Elements et qui passe par un point donne


lecrabe

Messages recommandés

Ah oui c'est marrant, j'y pensais (le cadr) lors de l'écriture du programme ! Mais voyant que ça fontionnait je n'ai pas corrigé. BricsCad quoi ah ah

 

Pour le trim, les options "_edge" et "_extend" sont activées dans ce but, justement : Elle permettent d'étendre les entités pour "forcer" la coupure non physiques.

 

Oui, le fameux changement de SCU. J'avoue avoir encore du mal avec ces maudites coordonnées qui sont pourtant le coeur du logiciel ! La fonction trans est puissante et un peu compliquée à la fois, faut vraiiiiment que je m'y colle une bonne fois pour toute.

 

Merci encore pour tes précieux retours.

"Chacun compte pour un, et nul ne compte pour plus d'un."

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Ah ben si (gile) est dans la course !!! on fait quoi nous ?????

Bien sûr que c'est bien fait, c'est (gile)

 

De mon côté je travaille (quand je peux et je peux peu) sur ce type de raccordement.

J'arrive à faire l'arc par le calcul mais c'est pas dynamique et je ne gère que des lignes pour l'instant

Je ne lâche pas l'affaire même si, comme c'est arrivé souvent, je ne remets pas ma copie en temps et en heure.

 

Au fait, (gile) c'est en quoi ton truc, en C# ou en lisp ?

 

Amicalement

Lien vers le commentaire
Partager sur d’autres sites

Hello

 

OUI quand le Supreme Leader Gilles CAUSE, tout le monde ecoute et admire !

 

Bye, lecrabe

 

PS: ça m énerve GRAVE de voir que Microstation a "pique" dans AutoCAD plein de choses !

Et de l autre cote, Autodesk n a jamais regarde Microstation !!

Autodesk Expert Elite Team

Lien vers le commentaire
Partager sur d’autres sites

Merci pour les compliments, mais je ne suis pas sûr d'arriver à faire tout ce qu'il faudrait implémenter pour imiter correctement ce que fait Microstation (je me suis mis la barre assez haut : fonctionnement dynamique dans tous les plans avec des lignes polylignes, arcs et cercles). J'ai un peu avancé, toujours avec des segments droits (ligne ou polyligne), toujours dans le plan XY et avec la possibilité de changer le sens de l'arc par validation de d'une option, mais il reste du boulot...

 

C'est, bien sûr, écrit en C#/.NET. Je pense qu'en LISP on peut écrire (plus rapidement) quelque chose qui fonctionne sans fioritures, ni effets visuels.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Ma contribution avec deux segment droits, sans fonctionnement dynamique et sans contrôle des cas particuliers

 

(defun vlax-list->3D-point (lst / nlst)
 (while lst
   (setq nlst (cons (list (car lst) (cadr lst) (caddr lst)) nlst))
   (setq lst (cdddr lst))
 )
 (reverse nlst)
)



(defun c:cttp ()

 (setq AcDoc (vla-get-activeDocument (vlax-get-acad-object))
       Space (if (= (getvar "CVPORT") 1)
               (vla-get-PaperSpace AcDoc)
               (vla-get-ModelSpace AcDoc) 
             )
 )

 (setq S (getpoint "\nSommet : "))
 (setq SG (trans S 1 0))

 (setq d1 (trans (getpoint S "\nExtrémité d1 : ") 1 0))
 (setq seg1 (vla-addLine space (vlax-3d-point SG) (vlax-3d-point d1))) 

 (setq d2 (trans (getpoint S "\nExtrémité d2 : ") 1 0))
 (setq seg2 (vla-addLine space (vlax-3d-point SG) (vlax-3d-point d2))) 

 (setq A (trans (getpoint "\nPoint de passage : ") 1 0))

 ;; bissectrice
 (setq PT1 (polar SG (angle SG d1) 1))
 (setq PT2 (polar SG (angle SG d2) 1))
 (setq PTC (polar PT1 (angle PT1 PT2) (/ (distance PT1 PT2) 2.0)))
 (setq bissec (vla-addXline space (vlax-3d-point SG) (vlax-3d-point PTC)))

 ;; cercle de centre J
 (setq J (vlax-curve-getClosestPointTo bissec A))  
 (setq C1 (vla-addCircle Space (vlax-3d-point J) (distance A J)))

 ;; Cercle de centre I
 (setq I1 (inters J A SG d1 nil))
 (setq I2 (inters J A SG d2 nil))
 (if (< (distance A I1) (distance A I2))
   (setq I I1 seg seg1)
   (setq I I2 seg seg2)
 )
 
 (setq C2
   (vla-addCircle
     Space
     (vlax-3d-point (polar J (angle J I) (/ (distance I J) 2.0)))
     (/ (distance I J) 2.0)
   )
 )  

 ;; points d'intersection des deux cercles
 (setq lstpt (vlax-list->3d-point (vlax-invoke C1 'IntersectWith C2 acExtendNone)))

 ;; on prend le premier point d'intersection
 (setq K (car lstpt))
 ;; et on trace le cercle de centre I qui passe par K
 (setq C3 (vla-addCircle Space (vlax-3d-point I) (distance I K)))

 ;; on trouve les points d'intersection avec seg, je considère qu'il y en a deux sauf cas particuliers que je n'étudie pas
 (setq lstpt (vlax-list->3d-point (vlax-invoke seg 'IntersectWith C3 acExtendBoth)))
 (setq T1 (car lstpt))
 (setq T2 (cadr lstpt))

 ;; tracer les perpendiculaires
 (setq perp1 (vla-addXline Space (vlax-3d-point T1) (vlax-3d-point (polar T1 (+ (angle T1 SG) (/ pi 2)) 1))))
 (setq perp2 (vla-addXline Space (vlax-3d-point T2) (vlax-3d-point (polar T2 (+ (angle T2 SG) (/ pi 2)) 1))))

 ;; trouver les centres
 (setq lstpt (vlax-list->3d-point (vlax-invoke perp1 'IntersectWith bissec acExtendNone)))
 (setq O1 (car lstpt))
 (setq lstpt (vlax-list->3d-point (vlax-invoke perp2 'IntersectWith bissec acExtendNone)))
 (setq O2 (car lstpt))

 ;; points symétriques
 (setq T10 (vlax-curve-getClosestPointTo bissec T1))  
 (setq T20 (vlax-curve-getClosestPointTo bissec T2))
 (setq T11 (polar T10 (angle T1 T10) (distance T1 T10)))  
 (setq T21 (polar T20 (angle T2 T20) (distance T2 T20)))  

 ;; tracer les arcs
 (setq arc1 (vla-addArc Space (vlax-3d-point O1) (distance O1 T1) (angle O1 T1) (angle O1 T11)))  
 (setq arc11 (vla-addArc Space (vlax-3d-point O1) (distance O1 T1) (angle O1 T11) (angle O1 T1)))
 (if (< (distance A (vlax-curve-getClosestPointTo arc1 A)) (distance A (vlax-curve-getClosestPointTo arc11 A)))
   (vla-delete arc11)
   (vla-delete arc1)
 )

 (setq arc2 (vla-addArc Space (vlax-3d-point O2) (distance O2 T2) (angle O2 T21) (angle O2 T2)))
 (setq arc21 (vla-addArc Space (vlax-3d-point O2) (distance O2 T2) (angle O2 T2) (angle O2 T21)))
 (if (< (distance A (vlax-curve-getClosestPointTo arc2 A)) (distance A (vlax-curve-getClosestPointTo arc21 A)))
   (vla-delete arc21)
   (vla-delete arc2)
 )

 ;; supprimer les constructions
 (vla-delete bissec)
 (vla-delete C1)
 (vla-delete C2)
 (vla-delete C3)
 (vla-delete perp1)
 (vla-delete perp2)

 (princ)
)

 

Amicalement

Vincent

C'est au pied du mur que l'on reconnaît le maçon ! (Anonyme)

C’est en restant au pied du mur qu’on ne voit que le mur (Anonyme aussi)

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Je suis parti dans les mêmes directions que Zebulon_

Je n'ai pas encore terminé mais je viendrai proposer ma solution terminée

 

Merci du challenge, merci du partage

Ça m'a donné l'idée de faire un menu spécifique aux "arcs" sur da-code.fr car il y a de la matière à creuser...

 

Amicalement

 

Lien vers le commentaire
Partager sur d’autres sites

Hello

 

WAOUH !! Merci les Pros du Lisp / VLisp / Dotnet ...

 

Neanmoins quand je revois la Video MicroStation, JE PLEURE !!

 

Bon WE, Bye, lecrabe

 

PS: cela fait plusieurs fois que je fais des formations dans des collectivités Microstation qui passent sur AutoCAD / AutoCAD MAP...

Et ce pour 2 raisons :

1) La Principale : Covadis n'existe que sur AutoCAD / AutoCAD MAP !

2) Politique tarifaire de Bentley (L Éditeur de Microstation) "non satisfaisante" ! J'aimerais bien qu'on m'explique ?!

Autodesk Expert Elite Team

Lien vers le commentaire
Partager sur d’autres sites

J'ai commencé à travailler avec MicroStation 3.0, puis V4 dans les années 1990. Mais comme, au bout d'un moment, les clients du bureau d'études qui m'employait voulaient récupérer des fichiers dwg, notre patron a décidé de nous passer sur Autocad V12.

 

Je me souviens d'avoir pleuré amèrement également...

 

Amicalement, Vincent

C'est au pied du mur que l'on reconnaît le maçon ! (Anonyme)

C’est en restant au pied du mur qu’on ne voit que le mur (Anonyme aussi)

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Certes ce discours a été maintes fois entendu, mais, mais, mais...

Dans Microstation quand on veut créer "améliorer" avec une commande perso : y'-a-t'il un langage de programmation digne de ce nom ?

 

Amicalement

 

PS : j'ai pas retravaillé sur le lisp de raccord en question et en plus maintenant que je sais qu'une solution est donnée je me connais...il va finir sous le coude...

Lien vers le commentaire
Partager sur d’autres sites

Hello

 

Au fait n'oubliez pas le PS dans mon message d'hier a 4h47...

 

Vos remarques sont les bienvenues ?!

 

Et au fait dans quels domaines / fonctions AutoCAD est "meilleur" que USTN (SANS ajout de routines LSP) ??

 

Bye, lecrabe

Autodesk Expert Elite Team

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Oui didier, il y a des langages dignes de ce nom

VBA, MDL, C++

 

Sur ce lien , un site très riche en informations

J'entends souvent que le vba est mort etc.. , j'ai un doute

Voici une vidéo de modestes réalisations faites en vba justement

 

Juste un petit bémol,ce ne sont pas tant les langages supportés que les APIs et les fonctionnalités exposées qui importent.

Par exemple, l'API COM d'AutoCAD (la seule utilisable par le VBA AutoCAD) présente, à mon sens de graves lacunes (absence d'objets Point2D ou Point3d, pitoyable gestion des jeux de sélection, ...). Heureusement, en LISP on peut mixer les accès à l'API COM (fonctions vla-*) avec du "pur AutoLISP" pour palier à ces lacunes.

Et donc, à mon sens, ce qui fait la force d'AutoCAD, c'est de proposer, avec AutoLISP, un environnement de programmation à la fois très bien intégré et accessible au plus grand nombre (malgré les spécificités du langage LISP).

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Coucou

 

Réponse au PS du message #35

 

Assurément Covadis a développé un partenariat avec AutoDesk et de ce fait ils participent à la situation de monopole de cette société (et en plus ils travaillent sur MAP)

Je n'ai aucune idée des tarifs ni de la façon de faire de Bentley à propos de MicroStation, impossible de te répondre

 

Amicalement

 

Lien vers le commentaire
Partager sur d’autres sites

Revenons à nos moutons.

 

Tout d'abord un grand bravo à ceux qui s'accrochent en LISP. Je pense que challenge est difficile mais très intéressant.

 

De mon côté j'ai un peu avancé, ça fonctionne désormais avec les droites, les demi-droites, les lignes et les segments droits de polyligne (toujours dans le plan XY du SCG). J'ai aussi essayé de rendre le code plus robuste pour pouvoir gérer tout éventualité et préparer le terrain pour les arcs (même s'il n'est pas sûr que je le fasse). Plutôt que de déterminer l'arc généré en fonction des points de sélection des segments (comme semble le faire Microstation) j'ai préféré proposer la possibilité de parcourir les différentes solutions (uniquement 2 pour les segments droits) en validant l'option par défaut : "arc Suivant".

 

 

Pour ceux qui veulent tester, télécharger et installer ArcExtensionSetup.msi.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Par exemple, l'API COM d'AutoCAD (la seule utilisable par le VBA AutoCAD) présente, à mon sens de graves lacunes (absence d'objets Point2D ou Point3D, pitoyable gestion des jeux de sélection, ...)

Ok gile , je comprends mieux ton avis sur vba avec AutoCAD

Sur Microstation, je n'ai utilisé que le vba , mdl c++, bien trop compliqué pour moi et ce n'est pas mon métier

mais le vba ou plutot mvba y est très complet à mes yeux , voici l'aide incomplète , des point 2d 3d , des matrices , des matrices de transformation intégrées ...

 

Ton œil expert y trouvera , je pense, pas mal de choses intéressantes , ou pas

write a book about what ??

Lien vers le commentaire
Partager sur d’autres sites

Pour ceux que ça intéresse, le code avec quelques commentaires.

 

La classe Commands où est définie la commande ARCTAN et des méthodes pour la sélection des segments.

 

using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;
using AcDb = Autodesk.AutoCAD.DatabaseServices;

[assembly: CommandClass(typeof(Gile.AutoCAD.ArcExtension.Commands))]

namespace Gile.AutoCAD.ArcExtension
{
   public class Commands
   {
       static TransientManager transientMgr;
       static List<Drawable> drawables;

       /// <summary>
       /// Commande pour dessiner un arc tangent à deux entités rectilignes.
       /// </summary>
       [CommandMethod("ARCTAN")]
       public static void ArcTangent()
       {
           var doc = AcAp.DocumentManager.MdiActiveDocument;
           var db = doc.Database;
           var ed = doc.Editor;
           var ucs = ed.CurrentUserCoordinateSystem;

           transientMgr = TransientManager.CurrentTransientManager;
           drawables = new List<Drawable>();

           try
           {
               string errMsg;
               if (!TrySelectSegment(ed, "\nSélectionnez le premier segment: ", out Line2d line1, out errMsg))
               {
                   ed.WriteMessage(errMsg);
                   return;
               }
               if (!TrySelectSegment(ed, "\nSélectionnez le second segment: ", out Line2d line2, out errMsg))
               {
                   ed.WriteMessage(errMsg);
                   return;
               }
               if (line1.IsColinearTo(line2))
               {
                   ed.WriteMessage("Les segments sont colinéaires");
                   return;
               }
               using (var tr = db.TransactionManager.StartTransaction())
               using (var arc = new Arc())
               {
                   var jig = new ArcJig(arc, line1, line2);
                   var status = PromptStatus.Keyword;
                   while (status == PromptStatus.Keyword)
                   {
                       var result = ed.Drag(jig);
                       status = result.Status;
                       if (status == PromptStatus.OK && arc.EndAngle - arc.StartAngle != 0.0)
                       {
                           var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                           curSpace.AppendEntity(arc);
                           tr.AddNewlyCreatedDBObject(arc, true);
                       }
                   }
                   tr.Commit();
               }
           }
           catch(System.Exception ex)
           {
               ed.WriteMessage($"\n{ex.Message}\n{ex.StackTrace}");
           }
           finally
           {
               if (drawables.Count > 0)
               {
                   foreach (var drawable in drawables)
                   {
                       transientMgr.EraseTransient(drawable, new IntegerCollection());
                       drawable.Dispose();
                   }
               }
           }
       }

       /// <summary>
       /// Invite l'utilisateur à sélectionner une entité ou un segment linéaire.
       /// </summary>
       /// <param name="ed">Editeur courant.</param>
       /// <param name="message">Message d'invite.</param>
       /// <param name="line2d">Droite directrice du segment (output).</param>
       /// <param name="errMsg">Message d'erreur (output).</param>
       /// <returns>true, si la sélection est valide ; false, sinon.</returns>
       static bool TrySelectSegment(Editor ed, string message, out Line2d line2d, out string errMsg)
       {
           line2d = null;
           errMsg = null;
           var peo = new PromptEntityOptions(message);
           peo.SetRejectMessage("\nL'objet séléctionné n'est pas une droite, une demi droite, une ligne ou une polyligne.");
           peo.AddAllowedClass(typeof(Line), true);
           peo.AddAllowedClass(typeof(AcDb.Polyline), true);
           peo.AddAllowedClass(typeof(Xline), true);
           peo.AddAllowedClass(typeof(Ray), true);
           var per = ed.GetEntity(peo);
           if (per.Status != PromptStatus.OK)
           {
               errMsg = "*Annuler*";
               return false;
           }

           var id = per.ObjectId;
           var ucs = ed.CurrentUserCoordinateSystem;
           var plane = new Plane();
           using (var tr = new OpenCloseTransaction())
           {
               if (id.ObjectClass == RXObject.GetClass(typeof(Xline)))
               {
                   var xline = (Xline)tr.GetObject(id, OpenMode.ForRead);
                   if (xline.BasePoint.Z != 0.0 || xline.UnitDir.Z != 0)
                   {
                       errMsg = "La droite n'est pas sur le plan XY du SCG";
                       return false;
                   }
                   line2d = new Line2d(xline.BasePoint.Convert2d(plane), xline.UnitDir.Convert2d(plane));
               }
               else if (id.ObjectClass == RXObject.GetClass(typeof(Ray)))
               {
                   var ray = (Ray)tr.GetObject(id, OpenMode.ForRead);
                   if (ray.BasePoint.Z != 0.0 || ray.UnitDir.Z != 0)
                   {
                       errMsg = "La demi-droite n'est pas sur le plan XY du SCG";
                       return false;
                   }
                   line2d = new Line2d(ray.BasePoint.Convert2d(plane), ray.UnitDir.Convert2d(plane));
                   AddTransientRay(ray.BasePoint, ray.UnitDir.Negate());
               }
               else if (id.ObjectClass == RXObject.GetClass(typeof(Line)))
               {
                   var line = (Line)tr.GetObject(id, OpenMode.ForRead);
                   if (line.StartPoint.Z != 0.0 || line.EndPoint.Z != 0.0)
                   {
                       errMsg = "La ligne n'est pas sur le plan XY du SCG";
                       return false;
                   }
                   line2d = new Line2d(line.StartPoint.Convert2d(plane), line.EndPoint.Convert2d(plane));
                   AddTransientRay(line.StartPoint, line.EndPoint.GetVectorTo(line.StartPoint).GetNormal());
                   AddTransientRay(line.EndPoint, line.StartPoint.GetVectorTo(line.EndPoint).GetNormal());
               }
               else
               {
                   var pline = (AcDb.Polyline)tr.GetObject(id, OpenMode.ForRead);
                   if (pline.Normal != Vector3d.ZAxis || pline.Elevation != 0)
                   {
                       errMsg = "La polyligne n'est pas sur le plan XY du SCG";
                       return false;
                   }
                   var pt = pline.GetClosestPointTo(per.PickedPoint.TransformBy(ucs), false);
                   int index = (int)pline.GetParameterAtPoint(pt);
                   if (pline.GetSegmentType(index) != SegmentType.Line)
                   {
                       errMsg = "Le segment sélectionné n'est pas linéaire";
                       return false;
                   }
                   line2d = pline.GetLineSegment2dAt(index).GetLine();
                   AddTransientRay(pline.GetPoint3dAt(index), pline.GetPoint3dAt(index + 1).GetVectorTo(pline.GetPoint3dAt(index)).GetNormal());
                   AddTransientRay(pline.GetPoint3dAt(index + 1), pline.GetPoint3dAt(index).GetVectorTo(pline.GetPoint3dAt(index + 1)).GetNormal());
               }
               return true;
           }
       }

       /// <summary>
       /// Ajoute une demi-droite transitoire.
       /// </summary>
       /// <param name="point">Point de départ de la demi-droite.</param>
       /// <param name="vector">Direction de la demi-droite.</param>
       static void AddTransientRay(Point3d point, Vector3d vector)
       {
           var ray = new Ray() { BasePoint = point, UnitDir = vector };
           ray.ColorIndex = 8;
           drawables.Add(ray);
           transientMgr.AddTransient(ray, TransientDrawingMode.Highlight, 128, new IntegerCollection());
       }
   }
}

 

La classe ArcJig, c'est là que tout se passe.

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;

namespace Gile.AutoCAD.ArcExtension
{
   /// <summary>
   /// Fournit les méthodes pour afficher dynamiquement un arc tangent à deux segments passant par la position du curseur.
   /// </summary>
   class ArcJig : EntityJig
   {
       Arc arc;
       Point3d dragPt;
       Line2d line1, line2, axis;
       int index = 0;

       /// <summary>
       /// Crée une nouvelle instance de ArcJig.
       /// </summary>
       /// <param name="arc">Instance de Arc à mettre à jour dynamiquement.</param>
       /// <param name="line1">Première droite de tangence.</param>
       /// <param name="line2">Seconde droite de tangence.</param>
       public ArcJig(Arc arc, Line2d line1, Line2d line2) : base(arc)
       {
           this.arc = arc;
           this.line1 = line1;
           this.line2 = line2;
           axis = new Line2d();
       }

       /// <summary>
       /// Invite l'utilisateur à spécifier un point ou à faire défiler les arcs possibles.
       /// </summary>
       /// <param name="prompts">Aquisition des données.</param>
       /// <returns>Le résultat de l'invite.</returns>
       protected override SamplerStatus Sampler(JigPrompts prompts)
       {
           var options = new JigPromptPointOptions("\nSpécifiez un point sur l'arc ou [arc Suivant]: ", "Suivant");
           options.Keywords.Default = "Suivant";
           options.UserInputControls = UserInputControls.NullResponseAccepted;
           var result = prompts.AcquirePoint(options);
           if (result.Status == PromptStatus.Keyword)
           {
               index++;
               return SamplerStatus.OK;
           }
           else
           {
               if (result.Value.IsEqualTo(dragPt))
                   return SamplerStatus.NoChange;
               dragPt = result.Value;
               return SamplerStatus.OK;
           }
       }

       /// <summary>
       /// Met à jour l'arc en fonction du résultat à l'invite.
       /// </summary>
       /// <returns>true.</returns>
       protected override bool Update()
       {
           var point = dragPt.Convert2d(new Plane());
           var arcs = GetTangentArcs(point);
           if (arcs == null)
           {
               arc.StartAngle = arc.EndAngle = 0.0;
           }
           else
           {
               var arc2d = arcs[index % arcs.Length];
               arc.Center = new Point3d(arc2d.Center.X, arc2d.Center.Y, 0.0);
               if (arc2d.Radius > 0.0)
                   arc.Radius = arc2d.Radius;
               arc.StartAngle = arc2d.StartAngle + arc2d.ReferenceVector.Angle;
               arc.EndAngle = arc2d.EndAngle + arc2d.ReferenceVector.Angle;
           }
           return true;
       }

       /// <summary>
       /// Définit l'axe de symétrie entre les deux droites en fonction de la position du point.
       /// </summary>
       /// <param name="point">Point déterminant le secteur de l'axe.</param>
       void SetAxis(Point2d point)
       {
           if (line1.IsOn(point) || line2.IsOn(point))
               return;
           if (line1.IsParallelTo(line2))
           {
               var pt = line1.PointOnLine;
               var segment = new LineSegment2d(pt, line2.GetClosestPointTo(pt).Point);
               axis = new Line2d(segment.MidPoint, line1.Direction);
           }
           else
           {
               var intersPt = line1.IntersectWith(line2)[0];
               if (intersPt.IsEqualTo(point))
                   return;
               var dir = intersPt.GetVectorTo(point);
               var dir1 = line1.Direction;
               var dir2 = line2.Direction;
               if (IsClockWise(dir, dir1))
               {
                   if (IsClockWise(dir, dir2))
                       axis = new Line2d(intersPt, dir1 + dir2.Negate());
                   else
                       axis = new Line2d(intersPt, dir1 + dir2);
               }
               else
               {
                   if (IsClockWise(dir, dir2))
                       axis = new Line2d(intersPt, dir1 + dir2);
                   else
                       axis = new Line2d(intersPt, dir1 + dir2.Negate());
               }
           }
       }

       /// <summary>
       /// Evalue si les vecteurs tournent en sens horaire.
       /// </summary>
       /// <param name="v1">Premier vecteur.</param>
       /// <param name="v2">Second vecteur.</param>
       /// <returns>true, si le sens de rotation est le sens horaire ; false, sinon.</returns>
       bool IsClockWise(Vector2d v1, Vector2d v2) => v1.X * v2.Y - v2.X * v1.Y < 0.0;

       /// <summary>
       /// Calcule les arcs tangents aux deux droites passant par le point.
       /// </summary>
       /// <param name="point">Point de passage des arcs.</param>
       /// <returns>Une collection d'arcs ou null en cas d'impossibilité géométrique</returns>
       CircularArc2d[] GetTangentArcs(Point2d point)
       {
           SetAxis(point);
           var perp = axis.GetPerpendicularLine(point);
           var inters = axis.IntersectWith(perp);
           if (inters == null)
               return null;
           var cen = inters[0];
           inters = perp.IntersectWith(line1);
           if (inters == null)
               return null;
           var pt1 = inters[0];
           inters = perp.IntersectWith(line2);
           if (inters == null)
               return null;
           var pt2 = inters[0];
           var tol = new Tolerance(1e-8, 1e-6);
           double radius;
           CircularArc2d arc2d;
           if (point.IsEqualTo(pt1, tol))
           {
               cen = line1.GetPerpendicularLine(pt1).IntersectWith(axis)[0];
               radius = cen.GetDistanceTo(pt1);
               if (radius == 0.0)
                   return null;
               var vector = axis.Direction * radius;
               pt2 = pt1.Mirror(axis);
               arc2d = new CircularArc2d(pt1, cen - vector, pt2);
               if (arc2d.IsClockWise)
                   return new[] { new CircularArc2d(pt2, cen - vector, pt1), new CircularArc2d(pt1, cen + vector, pt2) };
               else
                   return new[] { arc2d, new CircularArc2d(pt2, cen + vector, pt1) };
           }
           if (point.IsEqualTo(pt2, tol))
           {
               cen = line2.GetPerpendicularLine(pt2).IntersectWith(axis)[0];
               radius = cen.GetDistanceTo(pt2);
               if (radius == 0.0)
                   return null;
               var vector = axis.Direction * radius;
               pt1 = pt2.Mirror(axis);
               arc2d = new CircularArc2d(pt1, cen - vector, pt2);
               if (arc2d.IsClockWise)
                   return new[] { new CircularArc2d(pt2, cen - vector, pt1), new CircularArc2d(pt1, cen + vector, pt2) };
               else
                   return new[] { arc2d, new CircularArc2d(pt2, cen + vector, pt1) };
           }
           if (point.IsEqualTo(cen))
           {
               radius = pt1.GetDistanceTo(cen);
           }
           else
           {
               var c1 = new CircularArc2d(cen, cen.GetDistanceTo(point));
               var seg = new LineSegment2d(cen, pt1);
               var c2 = new CircularArc2d(seg.MidPoint, seg.Length / 2.0);
               inters = c1.IntersectWith(c2);
               if (inters == null)
                   return null;
               radius = pt1.GetDistanceTo(inters[0]);
           }
           pt2 = pt1 - line1.Direction * radius;
           pt1 += line1.Direction * radius;
           arc2d = new CircularArc2d(pt1, point, pt1.Mirror(axis));
           if (arc2d.IsClockWise)
               return new[] { new CircularArc2d(pt1.Mirror(axis), point, pt1), new CircularArc2d(pt2, point, pt2.Mirror(axis)) };
           else
               return new[] { arc2d, new CircularArc2d(pt2.Mirror(axis), point, pt2) };
       }
   }
}

  • Upvote 2

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Hello Gilles (et Didier)

 

*** Pour Gilles ***

 

1) C BEAU !

 

2) Presenter les multiples solutions (2 en fait) C TOP !

 

3) Si jamais tu reussis a le faire depuis des Arcs ou Cercles (ou Arcs dans des Polylignes),

ce sera presque comme sur MicroStation !?

 

*** Pour Didier et TOUS ***

 

4) RAPPEL COVADIS 1 : COVADIS n'exige pas un AutoCAD MAP !

Environ 70-80% des Covadis tournent par dessus AutoCAD MAP

Et le reste par dessus : ACAD , ACAD Architecture , ACAD CIVIL ...

 

5) RAPPEL COVADIS 2 : Mais la preparation SIG ESRI Shape, Import / Export IMX pour communiquer avec InfraWorks, exigent un AutoCAD MAP !!

 

Bye, lecrabe

  • Upvote 1

Autodesk Expert Elite Team

Lien vers le commentaire
Partager sur d’autres sites

Dac avec lecrabe, C'est beau..

 

@gile : Pardonne mon ignorance, je ne connais rien en C#/.NET :

 

- De manière générale quel est l'intérêt d'écrire en .net plutôt qu'en Lisp en dehors du côté "temps réel" (là tu vas me sortir un sujet écrit en 2012, je le sens bien ! ^^ )

- Tu écris ça sur quoi ? J'ai cru lire ici que tu conseillais les versions Express gratuites Visual C# Express ou Visual VB Express.

- Je suppose que tu compiles en .msi (ou .exe d'ailleurs) avec ce même outil ?

 

Merci !

"Chacun compte pour un, et nul ne compte pour plus d'un."

Lien vers le commentaire
Partager sur d’autres sites

- De manière générale quel est l'intérêt d'écrire en .net plutôt qu'en Lisp en dehors du côté "temps réel" (là tu vas me sortir un sujet écrit en 2012, je le sens bien ! ^^ )

L'intérêt principal, c'est la puissance, pas tant en terme de rapidité d'exécution qu'en possibilités (APIs) offertes. Ici, par exemple, j'utilise les méthodes et propriétés d'objets purement géométriques (Point2d, Vector2d, Line2d, CircularArc2d, etc) qui facilitent grandement les différentes opérations tout en allégeant considérablement les besoins en ressource. Tu peux lire ce sujet.

 

- Tu écris ça sur quoi ? J'ai cru lire ici que tu conseillais les versions Express gratuites Visual C# Express ou Visual VB Express.

J'utilise Visual Studio Community 2017, l'IDE gratuit de Microsoft reconnu (même par des anti M$) comme étant le meilleur IDE du moment.

 

- Je suppose que tu compiles en .msi (ou .exe d'ailleurs) avec ce même outil ?

Les plugins AutoCAD sont compilé en DLL, mais on peut aussi compiler des EXE, des MSI etc.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant



×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité