AddBox _diagonal in Python

Is it possible to add a box to the 3dm with just the 2 diagonal points or do I need to construct the full 8 point list for the AddBox? Sorry for the newbie question but I AM just getting started.

You cannot do this with rhinoscriptsyntax currently. It is possible with RhinoCommon (sample below), but it’s pretty complex for a newbie… I would just stick with generating the 8 points for now…

–Mitch

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

pts=rs.GetPoints(max_points=2)
if pts and len(pts)==2:
    plane=rs.WorldXYPlane()
    box=Rhino.Geometry.Box(plane,pts)
    brep=Rhino.Geometry.Brep.CreateFromBox(box)
    sc.doc.Objects.AddBrep(brep)
    sc.doc.Views.Redraw()

(not the solution… just practicing :wink: )

the box2pt() function below should do the trick

import rhinoscriptsyntax as rs

def box2pt(p1, p2):

    pt0 = p1
    pt1 = rs.coerce3dpoint([p2[0], p1[1], p1[2]])
    pt2 = rs.coerce3dpoint([p2[0], p2[1], p1[2]])
    pt3 = rs.coerce3dpoint([p1[0], p2[1], p1[2]])
    pt4 = rs.coerce3dpoint([p1[0], p1[1], p2[2]])
    pt5 = rs.coerce3dpoint([p2[0], p1[1], p2[2]])
    pt6 = p2
    pt7 = rs.coerce3dpoint([p1[0], p2[1], p2[2]])

    rs.AddBox([pt0, pt1, pt2, pt3, pt4, pt5, pt6, pt7])


def input2pt():

    p1 = rs.GetPoint('Pick first point of box')
    if not p1: return
    
    p2 = rs.GetPoint('Pick second point of box')
    if not p2: return

    if p1[2] == p2[2]:
        print "Pick points with different heights"
        return

    box2pt(p1, p2)
    
input2pt()

Thanks Jeff - that gets me going in the right direction and has elegance.

Is it reasonable to think I can turn this box2pt into a class that gets reused for multiple objects a script with different variables for the points 1 & 2 each object?

I know I have a lot of learning here and greatly appreciate the help of this community. I can do what I want in GrassHopper but want to turn the definition into a plugin with a GUI. Python seems the ticket for that but I am just beginning with the language.

i don’t know… i’ve still yet to make a class in a script :slight_smile: (as in-- i’m inexperienced / just learning)

but it can just be a function in a script then it’s reusable… if you put this:

def box2pt(p1, p2):

    pt0 = p1
    pt1 = rs.coerce3dpoint([p2[0], p1[1], p1[2]])
    pt2 = rs.coerce3dpoint([p2[0], p2[1], p1[2]])
    pt3 = rs.coerce3dpoint([p1[0], p2[1], p1[2]])
    pt4 = rs.coerce3dpoint([p1[0], p1[1], p2[2]])
    pt5 = rs.coerce3dpoint([p2[0], p1[1], p2[2]])
    pt6 = p2
    pt7 = rs.coerce3dpoint([p1[0], p2[1], p2[2]])

    rs.AddBox([pt0, pt1, pt2, pt3, pt4, pt5, pt6, pt7])

… in a script, you could just keep calling it with

box2pt(point1, point2)
box2pt(ptA, ptB)
box2pt((x,y,z), (x,y,z))
box2pt(thispoint, thatpoint)
etc...

so yeah, any time you feed the function 2 points, it will draw a box using those two points for the diagonals and will make the other 6 points automatically.

As Jeff said, you don’t really need to make a class for this. A simple function definition as he showed is just fine, store it somewhere in your “library” and reuse it as needed. Encapsulating bits of code like this to make reusable custom functions is a very good idea.

Along those lines, a variation of my first post as a custom function, it has a third optional argument… In addition to passing the two corner points, you can also pass a plane. If you omit the plane argument, a World oriented box is constructed by default. If you pass a plane, the box will be aligned with the plane (in the example the active CPlane, but it could be any plane). To test, create a custom CPlane in the perspective viewport and two points to snap to, then run the script. If it’s not possible to create the box, in theory nothing will happen…

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def Box2Pts(ptA,ptB,plane=None):
    if plane is None: plane=rs.WorldXYPlane()
    box=Rhino.Geometry.Box(plane,[ptA,ptB])
    brep=Rhino.Geometry.Brep.CreateFromBox(box)
    if brep:
        rc=sc.doc.Objects.AddBrep(brep)
        sc.doc.Views.Redraw()
        return rc
    
def TestBox2Function():
    pt0=rs.GetPoint("Pick first corner of box")
    if not pt0: return
    pt1=rs.GetPoint("Pick second corner of box")
    if not pt1: return
    
    myWorldBox=Box2Pts(pt0,pt1)
    
    myCPBox=Box2Pts(pt0,pt1,rs.ViewCPlane())
    
TestBox2Function()

Perfect - thanks. This is just what I was looking for. That bit -> coerce3dpoint … beautiful.

Cplane not an issue at present but could become so… I’ll keep this in my hip pocket. Thanks for your thinking.