Hi.
Civil 3D has command: BreakFeatures.
I want to do the same but automatically.
I have a point3dcollection and feature line Id.
I want to create a new break for each point3d position.
Are there any ways to do this?
Perhaps I could use breakfeatures with "SendToExecute" but how can I do it without any requests to user?
Thank you.
Solved! Go to Solution.
Solved by joantopo. Go to Solution.
I don't see any API equivalent to this command.
Thanks,
Partha
Hi Partha.
And Could I do by prompt(command line) with "SendToExecute"?
Here we can select objectId before.
http://adndevblog.typepad.com/autocad/2012/09/using-object-id-in-sendcommand-method.html
I could send point1 and point2 too.
I don´t know if this way it is possible.
Partha, I've had a need in the past where it would've been nice for the Featureline object to implement the base curve object's GetSplitCurves() method. Of course this wouldn't work well with an elevated and or arc'ed f/l, which is probably why it hasn't been implemented.
Jeff -
You are right, with elevantions it won't help much.
However, let me know if we could simplify that and expose an API for developers usage. I would be happy to log an API wish list for the same to address in future release of Civil 3D.
Thanks,
Partha
I wanted to do an equivalent command MAPTRIM moreover recognize civil 3d objects as feature lines and 3 possibilities when this across polyline boundary (mpolygon):
-only break f/l that across with mpolygon
-break f/l and erase all objects within mpolygon.
-erase only objects that are whole within mpolygon.
Finally, I´m using "sendstringtoexecute" by prompt.
string strHandle1 = id.Handle.ToString(); string strEntName1 = "(handent \"" + strHandle1 + "\")"; Point3d pt3d = new Point3d(ptoCruce[0].X, ptoCruce[0].Y, 0); if (IsLineaCaracteristica == true) { Autodesk.Civil.DatabaseServices.FeatureLine ftLine = trans.GetObject(id, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead) as Autodesk.Civil.DatabaseServices.FeatureLine; double pk = ftLine.GetDistAtPoint(pt3d); string String_pk = functions.funciones_genéricas.stringdecimales(pk, 5); string strCommand = "BREAKFEATURES" + "\n" + strEntName1 + "\n" + "P" + "\n" + String_pk + "\n" + String_pk + "\n"; Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.SendStringToExecute(strCommand, true, false, true); Autodesk.AutoCAD.DatabaseServices.Entity entidad = trans.GetObject(IdLineaRotura, OpenMode.ForWrite) as Autodesk.AutoCAD.DatabaseServices.Entity; entidad.Erase(); } else { Autodesk.AutoCAD.DatabaseServices.Entity entidad= trans.GetObject(id, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Entity; string String_punto = functions.funciones_genéricas.stringdecimales(ptoCruce[0].X, 6)+","+functions.funciones_genéricas.stringdecimales(ptoCruce[0].Y, 6); string strCommand = "_BREAK" + "\n" + strEntName1 + "\n" + "P" + "\n" + String_punto + "\n" + String_punto + "\n"; Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.SendStringToExecute(strCommand, true, false, true); }
With feature lines, I have problems with point2d so I put it as station(distance) with "GetDistAtPoint()" method.
Hi.
I have a point2dcollection and I have to use it for break in each in every point2d.
I don´t have any problem the first time (first point), but the next times I need the new Id after the polyline/feature line has already been broken.
Are there any ways to get the new id from the broken entity?
I have tried this:
ObjectId idNuevaEntidad = Autodesk.AutoCAD.Internal.Utils.EntLast();
But EntLast doesn´t recognize the new entity after "break".
We don´t have to use "SendCommandToExecute".
We can use "getSplitCurves()" method which returns DBobjectCollection (new entities).
Unluckly, this method doesn´t exist yet for Civil 3D entities.
I have tried it and debugger throws "eNotImplementedYet".
I wish this for new API Civil 3D. (getSplitCurves() method implemented for feature lines).
Hi Jeff.
I will try to check it all and find out why it doesn´t work always.
Happy new year to all Autodesk community
Hi.
For " GetSplitFeaturelines" I am using point3dCollection as parameter instead doubleCollection, because I had problems with double values.
I have realised if we convert feature lines to polylines, you must also read Point Elevations from Feature Line, but when you create a new feature line from polyline, how do you know that one vertex should be Point Elevation instead Vertice?
Perhaps, one new property (extension polyline) that indicates it is a Point Elevation.
All the code is there to get the Elevation points as well. It woud be rather simple to create another extension that accepts a 3dpointcollection. I'll see what I can do tonight or tomorrow....babysitting grandkids the next few days, so time is tight.
Attached is a zip with a revised FeaturelineExtensions class. It provides a new override for the GetSplitFeaturelines method so you can pass either the Parameters in a DouvleCollection or the points in a 3dPointCollection. I also added the inclusion of the ElevationPoints that may be on a featureline. Note that I have not tested this new version, if you do try it and it gives you problems, let me know and I'll work on it some more. Just too tired to see straight right now.
Hi Jeff.
I like "BaseCurve2d" method for feature lines.
I have also polylines 3d and I need a similar method for those entities.
I have tried this but it is bad.
public static Polyline BaseCurve2d(this Polyline3d pol3d) { object line = pol3d.AcadObject; Polyline poly = new Polyline(); object[] args = new object[1]; args[0] = 1; Point3dCollection vertices = toolsC3D.FunctionsPolilineas.ObtenerVertices3D(pol3d.ObjectId); for (int i = 0, j = 0; i < vertices.Count; i++, j++) { Point2d pt = new Point2d(vertices[i].X,vertices[i].Y); Point3d pt3d = new Point3d(vertices[i].X, vertices[i].Y,vertices[i].Z); args[0] = pt3d.ToArray(); double bulge = (double)line.GetType().InvokeMember("GetBulgeAtPoint", System.Reflection.BindingFlags.InvokeMethod, null, line, args); poly.AddVertexAt(j, pt, bulge, 0, 0); } return poly; }
Could you make me this method (BaseCurve2d) for polyline 3d entities?
Thank you.
In fact, there is no need for any of the AcadObject stiuff that was used for featurelines since Polyline3d objects are fully exposed in .NET
public static Polyline BaseCurve2d(this Polyline3d pol3d) { Polyline poly = new Polyline(); Point3dCollection vertices = toolsC3D.FunctionsPolilineas.ObtenerVertices3D(pol3d.ObjectId); for (int i = 0, j = 0; i < vertices.Count; i++, j++) { Point2d pt = new Point2d(vertices[i].X,vertices[i].Y); poly.AddVertexAt(j, pt, 0, 0, 0); } return poly; }
Hi Jeff.
After this Christmas vacations, now I want finish this routine properly.
I was checking your code but I don´t get a rigth result with this sample (attached drawing file).
So, I decided to do a loop for each break point:
The steps are the following:
1)I have an objectId collection. (entities from layer´s filter)-----> IdColl which I do (foreach(objectId id in IdColl).
2)For each object, I use "IntersectWith ()" method with boundary polyline(I create a mpolygon from this) using as parameter "projection plane", to get all CrossPoints(pt3d) even they are with different elevations.(obviously, elevations from Crosspoints will be Z=0).
3)I do a "filter" to check if the CrossPoints are not equal that StartPoint or EndPoint of the entity.
In that case, I delete that point(Crosspoint) from collection.
4)In case that CrossPoint Collection>0 then;
I calculate again the proper elevation(Z) of only the first CrossPoint (I disregard the rest of CrossPoints).
To do this, I get 2 collections:
Point3dCollection vertex 3d from all vertex of object.
Point3dCollection vertex 2d from all vertex of object.
I get a "Curve" (in 2d) from object. For feature lines I use "BaseCurve2d()".
Then, I do this:
ptoCruce[0] = new Point3d(ptoCruce[0].X, ptoCruce[0].Y, FunctionsPolilineas.ElevationCurve(curva, pt2d, ListaVertices3d, ListaVertices2d));
*pt2d is the same ptoCruce[0] in 2d.
*ptoCruce[] is CrossPoint[] to understand it.
Where "ElevationCurve()" method is this:
public static double ElevationCurve(Curve cv, Point2d pt, Point3dCollection ListaVertices3D, Point2dCollection ListaVertices2D) //encontrar la elevación interpolada en dicho punto(pt). { double Elev = 0; Polyline pl = cv as Polyline; if (pl != null) { for (int i = 0; i < pl.NumberOfVertices; i++) { bool isOn = false; SegmentType segType = pl.GetSegmentType(i); if (segType == SegmentType.Arc) { Curve2d segArc = pl.GetArcSegment2dAt(i); if (segArc != null) { isOn = segArc.IsOn(pt); if (isOn == true) { //si el pto está en un segmento (arco) Point2d PuntoInicio = segArc.StartPoint; Point2d PuntoFinal = segArc.EndPoint; double distTotal = segArc.GetLength(segArc.GetParameterOf(segArc.StartPoint), segArc.GetParameterOf(segArc.EndPoint)); //distancia reducida. double distParcial = segArc.GetLength(segArc.GetParameterOf(segArc.StartPoint), segArc.GetParameterOf(pt)); //buscamos el indice en la lista del vértice de inicio del segmento. int indiceInicio = ListaVertices2D.IndexOf(PuntoInicio); double elevInicio = ListaVertices3D[indiceInicio].Z; int indiceFinal = ListaVertices2D.IndexOf(PuntoFinal); double elevFinal = ListaVertices3D[indiceFinal].Z; double elevTotal = elevFinal - elevInicio; double incrementoZ = (distParcial * elevTotal) / distTotal; Elev = elevInicio + incrementoZ; } } } else if (segType == SegmentType.Line) { Curve2d segLine = pl.GetLineSegment2dAt(i); if (segLine != null) { isOn = segLine.IsOn(pt); if (isOn == true) { //si el pto está en un segmento (recta) Point2d PuntoInicio = segLine.StartPoint; Point2d PuntoFinal = segLine.EndPoint; double distTotal = segLine.GetLength(segLine.GetParameterOf(segLine.StartPoint), segLine.GetParameterOf(segLine.EndPoint)); //distancia reducida. double distParcial = segLine.GetLength(segLine.GetParameterOf(segLine.StartPoint), segLine.GetParameterOf(pt)); //buscamos el indice en la lista del vértice de inicio del segmento. int indiceInicio = ListaVertices2D.IndexOf(PuntoInicio); double elevInicio = ListaVertices3D[indiceInicio].Z; int indiceFinal = ListaVertices2D.IndexOf(PuntoFinal); double elevFinal = ListaVertices3D[indiceFinal].Z; double elevTotal = elevFinal - elevInicio; double incrementoZ = (distParcial * elevTotal) / distTotal; Elev = elevInicio + incrementoZ; } } } } //end for } return Elev; }
which returns the properly elevation for PointCross (PointCross[0]).
This is a interpolated elevation.
Perhaps, this method could be shorter.
then, I do:
DBObjectCollection dbc = LR_FT.GetSplitFeaturelines(ptoCruce[0]);
but in this case, the parameter is a Point3d, not a Point3dCollection.
I add those objects in the drawing and I add their Id into IdColl.
I could do the same with CrossPointCollection instead I use only the first point but I had problems with GetSplitFeaturelines() method as show the sample.
Hi Jeff.
Don´t worry, I don´t hurry.
I don´t remeber if it was with Elevation Points or without them.Perhaps it was with them.
I would like to use this routine(command) for Survey Figures too.
Now, there are AddFetatureLineFromPoly() and GetSplitFeatureLine(), but I also needed : AddSurveyFigureFromPoly() and GetSplitSurveyFigure().
I´m newer and I don´t understand Invokemember strcuture.
About Survey Figures, they don´t use site but how can get the survey database from one survey figure? In API I think that this property doesn´t appears.