Draw largest rectangle within a limited shape

Draw largest rectangle within a limited shape

hs800150
Participant Participant
10,154 Views
66 Replies
Message 1 of 67

Draw largest rectangle within a limited shape

hs800150
Participant
Participant

Ok so this lisp might be too complicated but I would like to know if anyone knows a lisp to automate the largest rectangle within a space. I have attached a picture of what I mean. The red rectangle has to be a rectangle (90 degrees between each angle) and stay within the boundaries of the white shape. Lets say I can choose a width say 40' and the lisp automatically finds the largest length based on trial and error. Or if there is a lisp to find both the largest width and length that would work too. 

 

largest rec.PNG

0 Likes
Accepted solutions (1)
10,155 Views
66 Replies
Replies (66)
Message 2 of 67

CodeDing
Advisor
Advisor

@hs800150 ,

 

I know that this question has been asked before, but it's such a complicated solution, that I'm not sure where a solution lies. If anybody has one, I'd like to save it in my function library also.

 

Here are 2 sites which go into some methods. I know it's not a direct solution to your problem, but maybe I can look into this one day in the future and provide a solution of my own.

http://cgm.cs.mcgill.ca/~athens/cs507/Projects/2003/DanielSud/

https://d3plus.org/blog/behind-the-scenes/2014/07/08/largest-rect/

 

There are some people that have been around these parts for a while, if they don't have a solution stored somewhere then perhaps it's worth putting some effort into.

 

Best,

~DD

Message 3 of 67

john.uhden
Mentor
Mentor

When you say largest, I presume you mean by area, or do you intend to hold one of the dimensions?

(Not that I am at all close to any solution)

John F. Uhden

0 Likes
Message 4 of 67

hs800150
Participant
Participant

Either way I think. If one is easier to hold a dimension then that will work. I am looking for the largest width and length which in turn would result in the largest area

0 Likes
Message 5 of 67

ВeekeeCZ
Consultant
Consultant

@CodeDing wrote:

@hs800150 ,

...

https://d3plus.org/blog/behind-the-scenes/2014/07/08/largest-rect/

...


 

That shape looks familiar... anyone? John?

0 Likes
Message 6 of 67

john.uhden
Mentor
Mentor
Just asking because the largest width will not necessarily yield the
largest length, and vice versa. But if you are dealing with some kind of
material that has dimensional restrictions, then you would have to enter
that dimension.
I've done a lot of AutoLisp programming for a company that makes vinyl pool
liners. The design of the panels and their nesting makes a big difference
in the amount of material that will be used vs. wasted, and it ain't cheap.

John F. Uhden

0 Likes
Message 7 of 67

hs800150
Participant
Participant

This is for lot fits. I can choose the biggest width based on the product lineup. But whatever is easier. I extract the LengthxWidth data afterwards and plug it into a python/excel program to determine if house fits or not based on the biggest boxes I draw. If there was a lisp to automate the process would be even faster. The longest it takes me is individually drawing the "biggest rectangle" inside of the building lines.

0 Likes
Message 8 of 67

Sea-Haven
Mentor
Mentor

Just need to rewrite this in lisp https://github.com/alexandersimoes/d3plus/blob/master/src/geom/largestRect.coffee

 

Its the source code referred to in the Beekeecz post. Not sure what language but maybe compile and pass it a file of the pline vertices then use shell to run.

Message 9 of 67

hs800150
Participant
Participant

Its not python

0 Likes
Message 10 of 67

hak_vz
Advisor
Advisor

It is written in a coffeescript, a programming language that compiles into javascript

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 11 of 67

hak_vz
Advisor
Advisor

You have stated in one of your previous posts that you need this code to place max rectangle representing a building inside a building lot. There are mathematical algorithms for finding a rectangle with largest area, and brute force solutions. Available codes can be relatively easy rewritten to autolisp. I have an idea to tackle this problem in a different approach, but I need some information before I start writing a code.

 

Do some additional planing rules apply about placing a rectangle inside a shape as:

- minimal allowed distance to lot border

- at least one rectangle side parallel to lot shape border

- maximal allowed percentage that building can occupy inside a lot.

 

Here is an idea how I would tackle this problem without knowing about available algorithms.

 

Create two orthogonal vectors with origin on a polygon side oriented to inside polygon (it's a rectangle corner).

Rotate those two vector inside allowed 180 deg (or less) angle from current point to two point that define a polygon side (rotations in steps 1 deg or more). Find intersections for this two orthogonal  vectors  and place orthogonal rays so that it creates a rectangle with opposite diagonal point inside a  polygon. Opposite diagonal point is either on a polygon shape or it is a projection of a shorter rectangle side to other parallel side. With every step we retain a rectangle with maximum area.

In next iteration origin point is moved for some acceptable step (let say 0,5') along a polygon side and procedure repeats. Procedure ends when all polygon sides are tested.

 

Please give us much more details about how you want a rectangle placed inside a shape since solution can be as simple as few lines of code, or it can take a lots of effort to do it. 

 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 12 of 67

Kent1Cooper
Consultant
Consultant

I agree that some criteria or constraints would be helpful.  Just as an example of the potential complications, if you say that the result should have a side that lies along some side of the perimeter, then in certain situations you will not  get the largest possible rectangle.  In a regular octagon [yellow], the largest possible rectangle [red square] only touches the perimeter at corners, and does not  have any edge that lies on [or even parallel to] a perimeter edge:

LargestRect.PNG

Kent Cooper, AIA
0 Likes
Message 13 of 67

john.uhden
Mentor
Mentor

Worry not, Kent.  I don't think any planning board would approve your yellow lot.🙄

John F. Uhden

0 Likes
Message 14 of 67

john.uhden
Mentor
Mentor

I know nothing about Chile, other than maybe that's where Butch and Sundance met their end.

Yes, we could do something like that in AutoLisp with vl-stuff.

John F. Uhden

0 Likes
Message 15 of 67

hs800150
Participant
Participant

@hak_vz 

 

So the rectangle can touch the border of the shape

There is no maximum percentage for the rectangle

 

I think one rectangle side would need to be parallel to one side of the lot shape border. I am thinking in the code you choose the side the rectangle needs to be parallel to the lot border. Most of the lots aren't complicated. I have attached which line I would choose the rectangle to be parallel to if the lot is a cul-de-sac lot.

 

If I choose the BOLD red line I drew then one side of the rectangle would be parallel to that line and go through iterations until it finds the largest fit. Same steps would apply to the BOLD green line as well. Red and Green would be two different iterations. Let me know if there is more information that you need. These are the only constraints I can think of. 

 

Let me know if you have any better ideas. 

 

lot fit1.PNG

 

 

0 Likes
Message 16 of 67

hs800150
Participant
Participant

@hak_vz 

 

Also I wanted to add if its possible to select multiple borders and lines so the largest rectangle fit could potentially find the largest fit for all the lots I select at once?  Or is that too complicated to use a for loop for this type of problem?

0 Likes
Message 17 of 67

CodeDing
Advisor
Advisor

I'm trying to work on a program for this version:

https://d3plus.org/blog/behind-the-scenes/2014/07/08/largest-rect/

 

Pros:

- works on concave & convex shapes

 

Cons:

- relatively slower than convex methods

- approximate, can not guarantee 100% largest shape (but will be close)

- would not work with curves/arcs (I cannot personally code such a masterpiece, but let's start small then improve)

 

I am limited on time right now, but if anybody gets bored we can create some sub-functions together..

I'm in the meat & potatoes of it right now, So take a look, and given my Input parameters of the "RIPL_CreateCorners" function, I will need help creating something similar to this workflow:

 

 

(foreach angle angles
  (foreach iPoint iPoints
    {determine perpendicular lines @ iPoint, length, points of intersection on polyline}
    {create 2 mid points, 1 for each perpendicular line}
    (foreach aspectRatio aspectRatios
      {test if fits, ignore areas smaller than max area so far}
      {compare to max area so far, save if largest and fits}
    );foreach
  );foreach
);foreach

 

 

 

Here's my current progress. (note that If you were to load this and select a polyline, I have the program create a polyline showing all of my currently calculated inner Points (iPoints).

My goal is to have the "RIPL_CreateCorners" function return the 4 corners of the largest area rectangle (in clockwise order), that seems more useful to me than returning an entity, since not everybody would want to draw an entity, but rather analyze the height/width/area/etc.

 

I know it may be a lot to absorb, but if you get bored, check out the link and create a quick sub function.

 

 

(defun RIPL_LWPoly (lst cls)
  (entmakex (append (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline")
                          (cons 90 (length lst)) (cons 70 cls))
                    (mapcar (function (lambda (p) (cons 10 p))) lst)))
);defun

(defun LM:Collinear-p (p1 p2 p3)
;by Lee Mac: http://lee-mac.com/mathematicalfunctions.html#geometric
    (
        (lambda ( a b c )
            (or
                (equal (+ a b) c 1e-8)
                (equal (+ b c) a 1e-8)
                (equal (+ c a) b 1e-8)
            )
        )
        (distance p1 p2) (distance p2 p3) (distance p1 p3)
    )
);defun

(defun RIPL_PointIsInside (Point PointsList / PY P1Y P2Y)
;from user VovKa @ https://www.cadtutor.net/forum/topic/13233-identify-a-polyline-by-a-point-inside-this-polyline/?do=findComment&comment=110307
;works with polygons only, i.e. if (equal (car PointsList) (last PointsList))
 (if (cdr PointsList)
   (/=	(and (or (and (<= (setq	PY (cadr Point)
				P2Y (cadadr PointsList)
				P1Y (cadar PointsList)
			  );setq
			  PY
		      );<=
		      (< PY P2Y)
		 );and
		 (and (> P1Y PY) (>= PY P2Y))
	     );or
	     (> (car Point)
		(+ (* (/ (- PY P1Y) (- P2Y P1Y))
	      	      (- (caadr PointsList) (caar PointsList))
		   );*
		   (caar PointsList)
		);+
	     );>
	);and
	(RIPL_PointIsInside Point (cdr PointsList))
   );/=
 );if
);defun

(defun RIPL_CreateInternalPoints (verts / pts p1 p2 iPoints)
  (setq pts (cdr verts))
  (repeat (length pts)
    (setq p1 (car pts) pts (cdr pts))
    (foreach pt pts
      (setq p2 (polar p1 (angle p1 pt) (* 0.5 (distance p1 pt))))
      (if (and (RIPL_PointIsInside p2 verts)
               (not (LM:Collinear-p p1 p2 (car pts))))
        (setq iPoints (cons p2 iPoints))
      );if
    );foreach
  );repeat
  iPoints
);defun

(defun RIPL_CreateCorners (verts iPoints angIncr aspMax aspIncr / corners tmp aspRat areaMax areaCur)
  ;create aspect ratios
  (setq aspRat '(1) tmp 1.0)
  (while (<= (setq tmp (+ tmp aspIncr)) aspMax) (setq aR (cons tmp aR)))
  (setq aR (reverse aR))
  (setq ang 0.0 areaMax 0.0)
  ;DO WORK HERE
  corners
);defun

(defun RIPL (e / corners g2g tmp eg verts iPoints angIncr aspMax aspIncr)
;Rectangle In Polygon (Largest, by area) (approximate)
;e - ename, of 2D polyline.
;returns - list or nil, list of 4 rectangle corners (in clockwise order) if found.
;initial checks
  (setq g2g t)
  (cond
    ((not (eq 'ENAME (setq tmp (type e))))
      (setq g2g nil) (prompt "\nRIPL Error: Bad argument type: ENAME ") (princ tmp))
    ((not (eq "LWPOLYLINE" (setq tmp (cdr (assoc 0 (setq eg (entget e)))))))
      (setq g2g nil) (prompt (strcat "\nRIPL Error: Bad entity type: LWPOLYLINE " tmp)))
    ((zerop (logand 1 (cdr (assoc 70 eg))))
      (setq g2g nil) (prompt "\nRIPL Error: Polyline not closed."))
  );cond
;begin work
  (if g2g
    (progn
      ;get vertices
      (foreach x eg (if (= 10 (car x)) (setq verts (cons (cdr x) verts))))
      (setq verts (reverse (cons (last verts) verts)))
      ;calculate internal points
      (setq iPoints (RIPL_CreateInternalPoints verts))
      ;create polyline showing internal points
      (RIPL_LWPoly iPoints 1)
      ;set variables for accuracy / efficiency
      (setq angIncr 1.0
            aspMax 15
            aspIncr 0.5
      );setq
      ;create rectangles, return corners
      (setq corners (RIPL_CreateCorners verts iPoints angIncr aspMax aspIncr))
    );progn
  );if
;return
  corners
);defun

(defun c:RIPL ( / e corners)
  (if (and (setq e (car (entsel "\nSelect 2D Polyline: ")))
           (setq corners (RIPL e)))
    (prompt "\nDraw Something");(RIPL_LWPoly corners 1)
  );if
  (princ)
);defun

 

 

Best,

~DD

 

0 Likes
Message 18 of 67

john.uhden
Mentor
Mentor

Just for clarity, I trust that the boundary polyline is not the lot boundary but made from filleting the building setbacks, which are most probably different for front, side, and rear yards.  No programmer is likely to figure out which is which without looking at the entire subdivision map.

John F. Uhden

0 Likes
Message 19 of 67

hak_vz
Advisor
Advisor

@hs800150Thanks for reply. I have guessed that you wont need much too complicated stuff so I started to write my code in following way (that is much similar to your last posts).

1) You select a polygon and an point on the edge on which rectangle edge should lie. Polygon points are rearranged in counter-clockwise direction. I have forgotten cul-de-sac lot but I hope it will work.

2) Verticals to chosen polygon edge are drawn from its edge point and intersections with other polygon segments are found (there are three possible cases).

3) Along verticals rectangle edges are created in a way so that we use shorter distance from starting edge. At intersection point that define shorter vertical rectangle edge, parallel to starting edge is created. In that way we define a part of original polygon inside which is our max rectangle. 

4) Starting from first intersection on opposite side all the way to second intersection iteration will run to find rectangle with max area. I will try to figure out how to include option so you can select size of edge that lies on polygon.

 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 20 of 67

hs800150
Participant
Participant

@john.uhden 

 

Yes the border is the building setbacks not the lot lines. But the programmer doesn't need to worry about which is which since we are only concentrating on the constraining shape which is the building setbacks. 

0 Likes