I want to load file with database.ReadDwgFile
i dont want use editor (i don't want use CommandFlags.Session)
after the load in the database (see my code for xdb), i want to select all bloc within a closed line entity (within the xdb)
but how to do that whitout editor (editor..SelectWindowPolygon )
here my code for load each file , and mémorize all block for each file
Dim CollDocOuvert As New Collection For Each NomFichier In Fenetre.CollFichier 'recherche et extraction des blocs Dim Fichier As New IO.FileInfo(NomFichier) If Fichier.Exists = True Then GestionAUTOCAD.TxtOnLigneCOmmande("Gestion du fichier : " & Fichier.Name & vbCrLf) 'ed.WriteMessage(vbCrLf & "Gestion du fichier : " & Fichier.Name) StatusLabelBas.Text = "Gestion de : " & NomFichier Me.Refresh() 'Application.doevent() System.Threading.Thread.Sleep(1) If CollDocOuvert.Contains(NomFichier.ToUpper) = False Then Dim xdb As Database = New Database(False, True) Using (xdb) Try xdb.ReadDwgFile(NomFichier, System.IO.FileShare.Read, False, "") 'Attention(s) 'il n'y a pas de doc ouvert, ne pas utiliser la fonction debug Dim CollBlocRef As New Collection 'Attention ici les liens BlockReferences sont inutilisable ! GestionBloc.GetDecompteBlocAvecAtt(False, CollBlocRef, False, False, False, "", True, xdb) Dim El(0 To 1) As Object El(0) = NomFichier El(1) = CollBlocRef CollGlobale.Add(El) Catch ex As System.Exception MsgBox("Impossible d'ouvrir le fichier : " & vbCrLf & NomFichier, MsgBoxStyle.Information, "Erreur :") End Try End Using Else Dim Dbo As Database = CollDocOuvert.Item(NomFichier.ToUpper).database 'le fichier est ouvert ! Dim CollBlocRef As New Collection GestionBloc.GetDecompteBlocAvecAtt(False, CollBlocRef, False, False, False, "", True, Dbo) Dim El(0 To 1) As Object El(0) = NomFichier El(1) = CollBlocRef CollGlobale.Add(El) End If StatusLabelBas.Text = "" Else GestionAUTOCAD.TxtOnLigneCOmmande("Fichier introuvable: " & Fichier.Name & vbCrLf) 'ed.WriteMessage(vbCrLf & "Fichier introuvable: " & Fichier.Name) End If Next CollDocOuvert.Clear() CollDocOuvert = Nothing
GestionBloc.GetDecompteBlocAvecAtt --> function for count and retrieve block from the xdb
GestionAutocad.TxtOnLigneCommand --> sub for write msg on editor.
CollGlobal is a collection
StatusLabelBar is a component of my form for write msg. is use me.refresh and a timer (1s) for refresh my form. (a trick i have found for do this [if you have better trick i take it.])
and for all : Happy New Year
Solved! Go to Solution.
Hi,
here you can find methods for evaluating if a point (blockreference insertion point) is inside or outside a polygon: >>>click<<<
(be careful with the ray method as this might fail with AutoCAD calculation of intersection points in some (rare) situations).
HTH, - alfred -
so thanks. i find this. :
Here is a "C++" implementation of the winding number algorithm for the inclusion of a point in polygon. We just give the 2D case, and use the simplest structures for a point and a polygon which may differ in your application. // Copyright 2000 softSurfer, 2012 Dan Sunday // This code may be freely used and modified for any purpose // providing that this copyright notice is included with it. // SoftSurfer makes no warranty for this code, and cannot be held // liable for any real or imagined damage resulting from its use. // Users of this code must verify correctness for their application. // a Point is defined by its coordinates {int x, y;} //=================================================================== // isLeft(): tests if a point is Left|On|Right of an infinite line. // Input: three points P0, P1, and P2 // Return: >0 for P2 left of the line through P0 and P1 // =0 for P2 on the line // <0 for P2 right of the line // See: Algorithm 1 "Area of Triangles and Polygons" inline int isLeft( Point P0, Point P1, Point P2 ) { return ( (P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y) ); } //=================================================================== // cn_PnPoly(): crossing number test for a point in a polygon // Input: P = a point, // V[] = vertex points of a polygon V[n+1] with V[n]=V[0] // Return: 0 = outside, 1 = inside // This code is patterned after [Franklin, 2000] int cn_PnPoly( Point P, Point* V, int n ) { int cn = 0; // the crossing number counter // loop through all edges of the polygon for (int i=0; i<n; i++) { // edge from V[i] to V[i+1] if (((V[i].y <= P.y) && (V[i+1].y > P.y)) // an upward crossing || ((V[i].y > P.y) && (V[i+1].y <= P.y))) { // a downward crossing // compute the actual edge-ray intersect x-coordinate float vt = (float)(P.y - V[i].y) / (V[i+1].y - V[i].y); if (P.x < V[i].x + vt * (V[i+1].x - V[i].x)) // P.x < intersect ++cn; // a valid crossing of y=P.y right of P.x } } return (cn&1); // 0 if even (out), and 1 if odd (in) } //=================================================================== // wn_PnPoly(): winding number test for a point in a polygon // Input: P = a point, // V[] = vertex points of a polygon V[n+1] with V[n]=V[0] // Return: wn = the winding number (=0 only when P is outside) int wn_PnPoly( Point P, Point* V, int n ) { int wn = 0; // the winding number counter // loop through all edges of the polygon for (int i=0; i<n; i++) { // edge from V[i] to V[i+1] if (V[i].y <= P.y) { // start y <= P.y if (V[i+1].y > P.y) // an upward crossing if (isLeft( V[i], V[i+1], P) > 0) // P left of edge ++wn; // have a valid up intersect } else { // start y > P.y (no test needed) if (V[i+1].y <= P.y) // a downward crossing if (isLeft( V[i], V[i+1], P) < 0) // P right of edge --wn; // have a valid down intersect } } return wn; } //===================================================================
i can translate the function isLeft but the other no .
how to convert a line (or point3DCollection) to a V[] = vertex points of a polygon
here my solution.
so the final code for the function (in vb.net) :
'************************************************************************************** 'isLeft(): tests if a point is Left|On|Right of an infinite line. '// Input: three points P0, P1, and P2 '// Return: >0 for P2 left of the line through P0 and P1 '// =0 for P2 on the line '// <0 for P2 right of the line '// See: Algorithm 1 "Area of Triangles and Polygons" Private Function isLeft(ByVal P0 As Point2d, ByVal P1 As Point2d, ByVal P2 As Point2d) As Double Return ((P1.X - P0.X) * (P2.Y - P0.Y) - (P2.X - P0.X) * (P1.Y - P0.Y)) End Function '************************************************************************************** '************************************************************************************** '// wn_PnPoly(): winding number test for a point in a polygon '// Input: P = a point, '// V[] = vertex points of a polygon V[n+1] with V[n]=V[0] '// Return: wn = the winding number (=0 only when P is outside) 'int Public Function wn_PnPoly(ByVal Pbloc As Point3d, ByVal V() As Point2d, ByVal n As Double) As Double Dim wn As Double = 0 '// the winding number counter Dim P As New Point2d(Pbloc.X, Pbloc.Y) '// loop through all edges of the polygon For i As Integer = 0 To n - 1 'for (int i=0; i<n; i++) { If (V(i).Y <= P.Y) Then '// edge from V[i] to V[i+1] '// start y <= P.y If (V(i + 1).Y > P.Y) Then '// an upward crossing If (isLeft(V(i), V(i + 1), P) > 0) Then '// P left of edge wn = wn + 1 '// have a valid up intersect End If End If Else '// start y > P.y (no test needed) If (V(i + 1).Y <= P.Y) Then '// a downward crossing If (isLeft(V(i), V(i + 1), P) < 0) Then '// P right of edge wn = wn - 1 '// have a valid down intersect End If End If End If Next Return wn End Function '**************************************************************************************
and the test code for this function :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.Hide() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim tr As Transaction = db.TransactionManager.StartTransaction() Try Dim per As PromptEntityResult = ed.GetEntity("Select a polyline") Dim OkContinue As Boolean = True If per.Status = PromptStatus.OK Then Dim lwp As Polyline = Nothing Try lwp = tr.GetObject(per.ObjectId, OpenMode.ForRead) Catch ex As Exception ed.WriteMessage(vbCrLf + "Not a polyline" & vbCrLf) OkContinue = False End Try If OkContinue = True Then Dim vn As Integer = lwp.NumberOfVertices Dim colpt() As Point2d = Nothing ReDim colpt(vn) For i As Integer = 0 To vn - 1 '// Could also get the 3D point here Dim pt As Point2d = lwp.GetPoint2dAt(i) colpt(i) = pt ed.WriteMessage(vbCrLf + pt.ToString()) Next colpt(vn) = lwp.GetPoint2dAt(0) ed.WriteMessage(vbCrLf + "FIN" + vbCrLf) Dim per2 As PromptEntityResult = ed.GetEntity("Select a Bloc") If per2.Status = PromptStatus.OK Then Dim bloc As BlockReference Try bloc = tr.GetObject(per2.ObjectId, OpenMode.ForRead) Dim x As Double x = GestionAutocadEntite.wn_PnPoly(bloc.Position, colpt, vn) ed.WriteMessage(vbCrLf + "sortie : " & x.ToString) Catch ex As Exception ed.WriteMessage(vbCrLf + "Not a bloc" & vbCrLf) End Try Else ed.WriteMessage(vbCrLf + "Pas d'entité selectionnée !" & vbCrLf) End If End If Else ed.WriteMessage(vbCrLf + "Pas d'entité selectionnée !" & vbCrLf) End If Finally tr.Commit() tr.Dispose() End Try End Sub
the function return 0 if the bloc selected is not in the polyline.
But warning : if the bloc is in a line of the polyline, the function say : out of the polyline..
i tested this, work fine. I have modify the entry of P for a point3D (BlockReference)
Thanks for your help
Have a look here, which can be used to solve the more general problem (any closed boundry that can be used to create a region):
http://www.theswamp.org/index.php?topic=43572.msg488632#msg488632
i have see this thanks but in the commentary :
So. me i need a code for all polyline in WCS or UCS.
but it is a good example for the
i need to upgrade my code, i see my fonction return false when the point is on à line of my polyline. So i have to adjuste the check if the point is on my polyline. 🙂
here my final function using wn_Poly :
'*********************************************************************** '** procedure de détection si un point est dans une région(polyline) ** '*********************************************************************** '** ENTREE : ** '** - Ligne : la polyline ** '** Attention vérifier avant que la polyligne ne se ** '** croise pas elle-même (IsPolylineSelfIntercept) ** '** - Bloc : Le bloc a tester ** '** SORTIE : ** '** - True si dedans sinon false ** '*********************************************************************** Public Function IsBlocInZoneFromPolyline(ByRef Bloc As BlockReference, ByRef Ligne As Polyline) As Boolean Dim OkRetour As Boolean = False '=========================================================================== 'Gestion des erreurs d'entrée : 'Si pas définit If IsNothing(Bloc) = True Or IsNothing(Ligne) = True Then Return OkRetour 'Si ligne non fermée If Ligne.Closed = False Then Return False '=========================================================================== '=========================================================================== 'génération des points d'entrée de la fonction de calcul + vérification simple ' si le point est sur la polyligne 'du point de test Dim pt As New Point2d(Bloc.Position.X, Bloc.Position.Y) 'pt de la ligne Dim vn As Integer = Ligne.NumberOfVertices Dim colpt() As Point2d = Nothing ReDim colpt(vn) For i As Integer = 0 To vn - 1 '// Could also get the 3D point here Dim pts As Point2d = Ligne.GetPoint2dAt(i) colpt(i) = New Point2d(pts.X, pts.Y) 'Test si le point est sur un segment de la polyline si oui exit ! Dim seg As Curve2d = Nothing Dim segType As SegmentType = Ligne.GetSegmentType(i) If (segType = SegmentType.Arc) Then seg = Ligne.GetArcSegment2dAt(i) ElseIf (segType = SegmentType.Line) Then seg = Ligne.GetLineSegment2dAt (i) End If If IsNothing(seg) = False Then OkRetour = seg.IsOn(pt) If OkRetour = True Then Return True End If End If Next 'ajout du point [0] pour finir la boucle ! colpt(vn) = Ligne.GetPoint2dAt(0) '=========================================================================== Dim RetFonction As Double RetFonction = wn_PnPoly(pt, colpt, vn) If RetFonction = 0 Then OkRetour = False Else OkRetour = True End If Return OkRetour End Function
and for the completion : the function needed for check if polyline dont intercept :
'*********************************************************************** '** procedure de détection si une polyline se recoupe ** '*********************************************************************** '** ENTREE : ** '** - Ligne : la polyline ** '** SORTIE : ** '** - True si croisement ** '*********************************************************************** Public Function IsPolylineSelfIntercept(ByRef Ligne As Polyline) As Boolean Dim OkRetour As Boolean = False 'Dim doc As Document = Application.DocumentManager.MdiActiveDocument 'Dim db As Database = doc.Database 'Dim ed As Autodesk.AutoCAD.EditorInput.Editor = doc.Editor Dim entities As DBObjectCollection = New DBObjectCollection() 'explosion des entités constituant la polyline Ligne.Explode(entities) For i As Integer = 0 To entities.Count - 1 For j As Integer = i + 1 To entities.Count - 1 Dim curve1 As Curve = entities(i) Dim curve2 As Curve = entities(j) Dim points As Point3dCollection = New Point3dCollection() curve1.IntersectWith(curve2, Intersect.OnBothOperands, points, IntPtr.Zero, IntPtr.Zero) For Each point As Point3d In points '// Make a check to skip the start/end points '// since they are connected vertices If (point = curve1.StartPoint Or _ point = curve1.EndPoint) Then If (point = curve2.StartPoint Or _ point = curve2.EndPoint) Then Continue For End If End If '// If two consecutive segments, then skip If (j = i + 1) Then Continue For End If ' ed.WriteMessage(vbCrLf & "Intersection point: " + point.ToString()) OkRetour = True Next Next '// Need to be disposed explicitely '// since entities are not DB resident entities(i).Dispose() Next Return OkRetour End Function
@Anonymous wrote:i have see this thanks but in the commentary :
/// Note that the sample code was designed to work with /// regions that lie in the WCS XY plane and points that /// lie in the same plane.So. me i need a code for all polyline in WCS or UCS.
but it is a good example for the
using Autodesk.AutoCAD.BoundaryRepresentation; // acdbmgdbrep.dlli need to upgrade my code, i see my fonction return false when the point is on à line of my polyline. So i have to adjuste the check if the point is on my polyline. 🙂
The sample shows the basic operation, which is inherintly a 2D computation,
and requires that candidate points lie exactly on the plane of the boundary,
so you would obviously need to project them onto boundary plane if they are
not already there.
If the candidate point is in the plane of the boundary, the code
should correctly indicate if the point lies exactly on an edge.
yes. but this code is already a little too hard for me. 😛 so to translate region on WCS to UCS. i know the basic only. I learn but only with code understandable for me. And with all this, i have to translate all my code from VB.net for Autocad V2010 to Autocad V2014 soon.
thanks for your help.
Can't find what you're looking for? Ask the community or share your knowledge.