Dose Bricscad have a native command to draw tin surface long section from path (2d polyline)?

aridzv
edited May 27 in 2D Drafting

Hi.

Is there a native Bricscad command\workflow to get a long section of a 2d polyline drawn on a tin surface like in the attached example (done with lisp)?

thanks,

Aridzv.

Comments

  • I am pretty sure have posted before have a look at "Civil Site Design" does way more than a long section, auto make layouts of the long section given Hor and Ver scales, with plan view also on same layout. Compatible with Bricscad.

    https://civilsitedesign.com.au/

  • Its_Alive
    edited May 28

    Python, but maybe this will get you close, maybe you can use AI to port it to lisp. The compute of baseline_z seems off though, I don’t know how to compute it, so it’s magic 900

    from pyrx import Ap, Db, Ed, Ge, Rx
    import traceback
    import math
    
    
    def get_2d_profile_data(polyline: Db.Polyline3d):
        """
        Computes 2D profile graph coordinates from a 3D polyline.
        Returns: (station_distances, elevations, points_3d)
        """
        points = polyline.toPoint3dList()
        station_distances = [0.0]
        elevations = [points[0].z]  # Extracted first item's Z elevation
        cumulative_distance = 0.0
    
        for i in range(len(points) - 1):
            pt1 = points[i]
            pt2 = points[i + 1]
    
            # Calculate flat 2D segment length in the XY plane
            dx = pt2.x - pt1.x
            dy = pt2.y - pt1.y
            segment_length = math.sqrt(dx * dx + dy * dy)
    
            cumulative_distance += segment_length
            station_distances.append(cumulative_distance)
            elevations.append(pt2.z)
    
        return station_distances, elevations, points
    
    
    @Ap.Command()
    def drawprofile():
        try:
            db = Db.curDb()
    
            # 1. Select the alignment 3D Polyline
            ps, id, _ = Ed.Editor.entSel("\nSelect 3D Polyline: ", Db.Polyline3d.desc())
            if ps != Ed.PromptStatus.eOk:
                raise RuntimeError("Selection failed.")
    
            # 2. Ask where to draw the new profile view in your drawing
            p_status, insertion_pt = Ed.Editor.getPoint("\nPick insertion point for profile view: ")
            if p_status != Ed.PromptStatus.eNormal:
                raise RuntimeError("Insertion point required.")
    
            # 3. Process the polyline data
            pl = Db.Polyline3d(id, Db.OpenMode.kForRead)
            stations, elevations, _ = get_2d_profile_data(pl)
    
            # 4. Determine adaptive baseline datum below the lowest point
            min_z = min(elevations)
            max_z = max(elevations)
            vertical_spread = max_z - min_z
            if vertical_spread == 0:
                vertical_spread = 10.0
            baseline_z = min_z - (vertical_spread * 0.5)
    
            # adaptive baseline seems wrong
            baseline_z = 900
    
            # Open current space for writing database entities
            btr = Db.BlockTableRecord(db.currentSpaceId(), Db.OpenMode.kForWrite)
    
            profile_graph_points = []
    
            # Define text sizing parameters relative to your landscape's scale
            # Adjust text_height if labels appear too small or large in your viewport
            text_height = vertical_spread * 0.05 if vertical_spread > 0 else 2.5
            text_offset = text_height * 0.5
    
            # 5. Generate and draw profile lines & text labels
            for i in range(len(stations)):
                # Map 3D Chainage -> Graph X | True Elevation -> Graph Y
                graph_x = insertion_pt.x + stations[i]
                graph_y = insertion_pt.y + (elevations[i] - baseline_z)
    
                top_pt = Ge.Point3d(graph_x, graph_y, 0.0)
                base_pt = Ge.Point3d(graph_x, insertion_pt.y, 0.0)
    
                profile_graph_points.append(top_pt)
    
                # Draw the vertical station drop lines (Light Gray)
                drop_line = Db.Line(top_pt, base_pt)
                drop_line.setColorIndex(9)
                btr.appendAcDbEntity(drop_line)
    
                # --- ADD STATION TEXT LABEL ---
                # Text position directly underneath the baseline axis
                text_pos = Ge.Point3d(graph_x, insertion_pt.y - text_offset, 0.0)
    
                # Format display string (e.g., "Sta: 140.50 | El: 923.40")
                label_string = f"Sta: {stations[i]:.2f}  El: {elevations[i]:.2f}"
    
                txt_ent = Db.Text()
                txt_ent.setPosition(text_pos)
                txt_ent.setHeight(text_height)
                txt_ent.setTextString(label_string)
                txt_ent.setColorIndex(7)  # White/Black adaptive text
    
                # Rotate text 270 degrees (-90) so it drops cleanly straight down without overlapping adjacent labels
                txt_ent.setRotation(3.0 * math.pi / 2.0)
    
                btr.appendAcDbEntity(txt_ent)
    
            # 6. Draw the continuous ground boundary across the top (Green)
            ground_line = Db.Polyline(len(profile_graph_points))
            for idx, pt in enumerate(profile_graph_points):
                ground_line.addVertexAt(idx, Ge.Point2d(pt.x, pt.y))
    
            ground_line.setColorIndex(3)  # Green
            btr.appendAcDbEntity(ground_line)
    
            # 7. Draw a solid baseline path boundary across the bottom (White/Continuous)
            base_line = Db.Line(
                Ge.Point3d(insertion_pt.x, insertion_pt.y, 0.0),
                Ge.Point3d(insertion_pt.x + stations[-1], insertion_pt.y, 0.0),
            )
            base_line.setColorIndex(7)
            btr.appendAcDbEntity(base_line)
            print(f"\nProfile view and vertical labels successfully drawn.")
    
        except Exception:
            print(traceback.format_exc())
    
    

  • @ALANH

    @Its_Alive

    Thanks for the replies.

    I have a lisp that do it.

    I was actually wendering if bricscad V26 have a native command to do it,

    so I dont have to use lisp or 3rd party app.

    @ALANH - see this discussion, mybe that is the discussion you ment?

    @Its_Alive - thanks, I'll try the py code.

  • @Its_Alive A couple of comments been doing Civil long sections for too many years, 40+. When you drape a 2d pline on a surface it looks at all the intersecting 3dfaces or TIN edges. It does not do actual say 10m spacings, but good long section software has 3 choices do 10m spacing, NS only or combo of both. The same applies to the cross-sections. when you add design control the choices become more critical about the final output.

    I started as a CIVIL software rep back in the 90's and software at that time was way more advanced than where Bricscad is at the moment, it needs a significant purchase of a CIVIL software company to catch up and be better than CIV3D.

    This is an old plot youtube V16 its now V26. Shows some of the power of the software.

  • Its_Alive
    edited May 28

    Oops, I misread the post, I thought Aridzv was looking for a lisp. I’m beginning to understand why civil software is expensive lol