Detail from clipping plane #sharingiscaring

Hi again,

Here is another script to speed up the “layouting” in Rhino 7. Instead of making a detail on a specific layout, aligning it to a clipping plane, making a correct scale etc. - lets reverse the process:

  1. Make clipping planes in 3d. It works with all directions, not only top projection. Pay attention to the orientation of the clipping plane.
  2. Adjust the clipping plane size, so it bounds the geometry - this will be used as the detail width and height in proper scale on the layout.
  3. Start the script - it will ask you to select one clipping plane you want change into a detail.
  4. Select the scale from the menu (or click CANCEL to provide your own)
  5. Select the layout you want to place the detail on.
  6. Pick the placement on the layout - it will be the left bottom corner of the detail.

The script will do the following:

  1. make a new detail in position provided by you, in selected scale.
  2. the name of the detail view will be the same as the name of the clipping plane (or name of the model view if clipping plane has no name)
  3. make the detail size the same as the clipping plane size in selected scale
  4. create a cPlane in the middle of the detail, oriented as clipping plane

Here is a small video:

Here is the code:



# Author: Pawel Jakub Tujakowski / kumulus.agency
# Version: 1.0
# Date: 2024.02.14
# detail_from_clippingplane.py 2024 by Pawel Jakub Tujakowski is licensed under Attribution-ShareAlike 4.0 International (https://creativecommons.org/licenses/by-sa/4.0/)

import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs


def detail_from_clippingplane():
    ### VARIABLES ###
    scales = ["1:1", "1:2", "1:5", "1:10", "1:20", "1:25", "1:50", "1:75", "1:100", "1:150", "1:200", "1:250", "1:400", "1:500", "1:1000", "1:2000", "1:5000"] 
    layoutNames = []

    ### SCRIPT WORKS IN MM ###
    sc.doc.PageUnitSystem = Rhino.UnitSystem.Millimeters

    ### PICK A CLIPPING PLANE ###
    frameId = rs.GetObject("Pick clipping plane for detail", rs.filter.clippingplane)
    if frameId == None:
        return()

    ### GET ALL LAYOUTS ###
    page_views = sc.doc.Views.GetPageViews()
    for page_view in page_views:
        layoutNames.append(page_view.PageName)

    ### FRAME SPECIFICATIONS ###
    frameName = rs.ObjectName(frameId)
    if frameName == None:
        frameName = rs.CurrentView()
    domainU = rs.SurfaceDomain(frameId, 0)
    domainV = rs.SurfaceDomain(frameId, 1)
    frameBoxLL = rs.EvaluateSurface(frameId, 0, 0)
    frameBoxUL = rs.EvaluateSurface(frameId, domainU[1], 0)
    frameBoxUR = rs.EvaluateSurface(frameId, domainU[1], domainV[1])
    frameU = rs.Distance(frameBoxUR,frameBoxUL)
    frameV = rs.Distance(frameBoxUL,frameBoxLL)
    midXYZ = (frameBoxUR+frameBoxLL)/2
    origin = frameBoxLL
    
    ### VECTORS NEEDED FOR CONSTRUCTION PLANES ETC. ###
    vectorU = rs.VectorCreate(frameBoxUL, frameBoxUR)
    vectorV = rs.VectorCreate(frameBoxLL, frameBoxUL)
    vectorW = rs.VectorCrossProduct(-vectorU, vectorV)
    normal = rs.VectorUnitize(vectorW)

    ### PICK SCALE FROM LIST OR OVERRIDE ###
    scale = rs.ListBox(scales, "Pick scale from the list or click CANCEL to override", "Scale", default = "1:50")

    if scale == None:
        scale = rs.StringBox("1:___",None,"Override scale")
        if scale == None:
            return()
        else:
            while scale.isdigit() != True :
                print "Scale must be an integer!"
                scale = rs.StringBox("1:___",None,"Override scale")
                if scale==None:
                    return
    else:
        scale = scale.replace("1:","")
    
    ### SCALE CALCULATIONS ###
    scaleMult = 1/eval(scale)
    frameSU = frameU*scaleMult
    frameSV = frameV*scaleMult

    ### SELECT LAYOUT TO PUT DETAIL ON ###
    layoutName = rs.ComboListBox(layoutNames, "Select layout")
    if layoutName == None:
        return()
    if layoutName: 
        for page_no in range(len(layoutNames)):
            if(layoutNames[page_no] == layoutName):
                layout = page_views[page_no]
                
    ### CREATE DETAIL WITH CORRECT NAME AND PLACEMENT, CREATE LOCAL CPLANE, ADD CLIPPING PLANE ###
                if layout: 
                    sc.doc.Views.ActiveView = layout
                    sc.doc.Views.Redraw()
                    basePoint = rs.GetPoint("Pick placement")
                    if basePoint:
                        detail = layout.AddDetailView(frameName, Rhino.Geometry.Point2d(basePoint.X,basePoint.Y), Rhino.Geometry.Point2d(basePoint.X+frameSU,basePoint.Y+frameSV), Rhino.Display.DefinedViewportProjection.Top)
                        if detail:
                            layout.SetActiveDetail(detail.Id)
                            detail.Viewport.SetCameraDirection(normal,True)
                            detail.Viewport.SetCameraTarget(midXYZ, True)
                            detail.CommitViewportChanges()
                            detail.DetailGeometry.IsProjectionLocked = True
                            detail.DetailGeometry.SetScale(1, sc.doc.ModelUnitSystem, scaleMult, sc.doc.PageUnitSystem)
                            detail.CommitChanges()
                            rs.ViewCPlane( None, rs.PlaneFromNormal(midXYZ, normal,-vectorV) )
                            clippingPlane = sc.doc.Objects.FindId(frameId)
                            clippingPlane.AddClipViewport(detail.Viewport,True)

if __name__ == "__main__":
    pageview = sc.doc.Views.ActiveView
    if type(pageview) == Rhino.Display.RhinoPageView:
        print "This tool only works in the model space."
    else:
        detail_from_clippingplane()


You can also download the script here:
https://www.dropbox.com/t/kMEA3LZC7xlZbo06

Enjoy!

2 Likes