Jump to content

MullinRJ

Member
  • Posts

    1,987
  • Joined

  • Last visited

Everything posted by MullinRJ

  1. FLIPPED doesnot have an axis implied when it it detected. Flipped Horizontally, and Flipped Vertically are the same thing, except the final rotations differ by 180°. VW default flip is vertical, meaning the rotat... — Okay, never mind. you figured it out. Raymond
  2. MullinRJ

    use matrix

    Good morning, @DomC. One thing about the Entity Matrix (EM) that is NOT in the documentation – The EM for symbols and images is encoded differently from all other 2D planar objects on the same plane. The EM for symbols and images contain information about their rotations on the plane, combined with the location and rotation of the plane where they reside. This means the EM for a symbol on a WP is NOT the same as that of a rectangle, line, locus, or circle on the same WP. The latter four will all have the same EM if they exist on the same WP, as the EM is supposed to define the WP, and not the object on the plane. I spent almost an entire summer figuring exactly how symbols and image EMs are put together and how to take them apart, only to realize that all I needed was a Working Plane's Reference ID to manipulate objects freely on Working Planes or move objects between them. Does Marionette have access to RefIDs? If not, you should request that it does. EMs are way too clunky to deal with, and they are not consistent between object types on the same plane. My 2¢, Raymond
  3. MullinRJ

    use matrix

    Hi @DomC, From the picture and movie you posted, you have everything you need to define a working plane (WP) at each vertex, with no additional math required. 1) Your WP Origin is the vertex p_corner. 2) The local WP Xaxis, or Uvec, is p1-p_corner (vector subtraction). You'll need to spin your own function for this if you don't want to import any modules. Easy. 3) Your WP Normal vector is p1xp2, or vs.CrossProduct(p1, p2), or vs.CrossProduct(p2, p1)*. 4) And your WP Yaxis, or Vvec, (which is not needed to define the plane, but may be nice to have) is CrossProduct(Normal, Uvec). To define a WP at point p_corner use: vs.SetWorkingPlaneN(p_corner, Normal, Uvec) Easy Peasy. You don't need to convert your 3DPoly points to rotation angles, but you can use vs.GetWorkingPlane() after you set the WP with vs.SetWorkingPlaneN() and VW will give you a set of rotation angles that will be equivalent. * The only finesse point concerns which side of the corner vertex is the UP side of the WP. Since the Poly is in 3D space, there really is no Up side and your Normal could point in in either direction. vs.CrossProduct(p1, p2), or vs.CrossProduct(p2, p1) point in opposite directions. If it's not important, use either one. If you are familiar with the Right Hand Rule, you can visualize which way the Normal vector points relative to the 3 points you're using to define the plane. If not, google Right Hand Rule and you will find tons of websites showing how to use it. There are lots of videos are out there. If I left anything out, let me know. Raymond
  4. MullinRJ

    use matrix

    @DomC, What do your 3 points represent? P1 = Plane's center point? P2-P1 = Plane's Normal vector? P3-P1 = Plane's X` axis (or U vector)? Or something else? I believe what you want is doable, but would require going back to college texts, or the internet, a bunch. Do you have a specific problem you are trying to solve? Raymond
  5. Have you tried saving your 2x image at 72 dpi? I have a very old memory whispering that it may be relevant. It’s an OLD memory so let me know if it is relevant. Thanks, Raymond
  6. You could create another button that has "place but don't close" functionality. It can have a keyboard shortcut assigned to it. If you did assign a keyboard shortcut to the OK / PLACE button, there is no way you could distinguish between the shortcut being pressed and the button being clicked. To have two functions in your dialog, you will need two buttons. Raymond
  7. Hello @Ian M., Though I don't have one written, it is possible to write a script that can be called by a worksheet to get your cable lengths. I think @Pat Stanfordor @michaelkmay have posted some example scripts in the past. Search the Forum for "Worksheet Script" (include the double quotes), or start here: A Pat Stanford Worksheet Script Tutorial. Raymond
  8. Hi @MarcelP102, Sweeps are tricky. You can individually scale the radius/diameter, but only if your view is looking down the center, i.e., along the axis of rotation. This would be a FRONT or a BACK view for an unrotated Sweep. You can then scale the height, but only if you are looking at a TOP, LEFT, RIGHT, or BOTTOM view of an unrotated Sweep. If the Sweep object is rotated, you have to set up custom views to access a local FRONT view, and then the local TOP view. I know this because it's how I scale sweeps in my Reshaper plug-in, and I can tell you it's a LOT of code to resize a Sweep. Another approach would be to completely un-rotate the Sweep, then jump to the FRONT view to scale the Sweep's diameter, and then the TOP view to scale the Sweep's height. When done, re-rotate the Sweep to its original angles. If necessary, move it back into position. Again, a lot of code. ***** In modern dialog code there is an Event Loop. In your example you call it "Dialog_Handler", but there is nothing in it. When you press the OK button, dialog item = 1, you need to read the EditReal fields into variables with GetEditReal() when this event is detected. Use a CASE statement on the "item" variable to detect different events. With those variables loaded you can execute your scaling code. You can either do this inside the dialog code, or outside after the dialog closes, but you only do so if the user pressed the OK button; item=1 inside the dialog, or Result=1 outside the dialog. Raymond
  9. Hello @MarcelP102, The big difference between Scale and HScale2D, is that Scale operates on all selected objects with no finesse, while HScale2D operates on a single item identified by its handle. There is a lot more control afforded by the latter command, but more diligence must be taken to pass meaningful parameters, thus making for longer scripts. I only modified your first script, and I added a clause in your CASE statement to show you how to scale Multiple Extrudes. Sweeps should be similar, but you have to scale the Ht (height) and Wid (width) dimensions the same, because Sweeps are always circular. The Thk (thickness) dimension can be scaled a different value, if you like. I also swapped out your two dialog calls for one call that allows you to enter 2 numbers at once. If you want "fancy", then you'll have to code a small custom dialog, but for quick and dirty, this gets the job done with a one-line call. All of my changes are commented. If you have any questions, please don't hesitate to write back. You're off to a good start. Enjoy, Raymond PROCEDURE RandomScaleObjects; {Scales each selected object in the active layer randomly within a user given range} {© 17-06-2022 Arnhem - The Netherlands, Marcel Plomp} {With the help of Pat Stanford and others} { 18 Jun 2022 - Show how to scale MExtrudes, and some small mods made by "Others". } {Licensed under the GNU Lesser General Public License} VAR rScaleFactor :REAL; rScaleMax, rScaleMin :REAL; rCenterX, rCenterY, rCenterZ :REAL; rCenterX1, rCenterY1, rCenterZ1 :REAL; { need more variables } Ht, Wid, Thk :REAL; { need more variables } iObjectType :INTEGER; Procedure WithIt(Hd:Handle); BEGIN iObjectType := GetTypeN(Hd); rScaleFactor := Round(100 * (Random*(rScaleMax - rScaleMin) + rScaleMin)) / 100; CASE iObjectType OF {Scales the Line, Rectangle, Oval, Polygon, Arc, Freehand, Text, Rounded rectangle and Polyline} 2..6,8,10,13,21: BEGIN HCenter(Hd, rCenterX, rCenterY); HScale2D(Hd, rCenterX, rCenterY, rScaleFactor, rScaleFactor, True); END; {Scales the Extrude, Sweep, Mesh, CSG Solid, Nurbs Curve and Nurbs surface} {3D Polygon = 25, Sweep=34 and Multi extrude=38 does not work??} 24, 40, 84, 111, 113: BEGIN HCenter(Hd, rCenterX, rCenterY); HScale3D(Hd, rCenterX, rCenterY, 0, rScaleFactor, rScaleFactor, rScaleFactor); END; 38: BEGIN { MExtrude } Get3DCntr(Hd, rCenterX, rCenterY, rCenterZ); { original 3D center } Get3DInfo(Hd, Ht, Wid, Thk); { 3D Size } Set3DInfo(Hd, Ht*rScaleFactor, Wid*rScaleFactor, Thk*rScaleFactor); Get3DCntr(Hd, rCenterX1, rCenterY1, rCenterZ1); { center after scaling } Move3DObj(Hd, rCenterX-rCenterX1, rCenterY-rCenterY1, rCenterZ-rCenterZ1); { move it back } END; 15: BEGIN { Symbol } SetObjectVariableInt(Hd, 101, 2); SetObjectVariableReal(Hd, 102, rScaleFactor); END; {Look into if I want to add architectural objects like: 68,71,81,83,86,89 Bitmap (=14) can be scaled with Hscale2D but moves in place..} END; END; { WithIt } BEGIN { Use standard Point Dialog to collect 2 numbers. } PtDialog('Enter Max and Min scale factors in X&Y fields below.', '1.0', '0.01', rScaleMax, rScaleMin); ForEachObject(WithIt, InSymbol & VSEL); { don't need excess parens } ReDrawAll; END; Run(RandomScaleObjects);
  10. If you are using GetPtL(), GetLine(), or any of the other interactive functions to draw your path, then YES, you can test the Command, Option, CapsLock, and Shift functions to see if any were pressed when an interactive function was running. If you are using standard VW Drawing Tools, then I don't think so. I'm not your final authority, so wait to see if better advice arrives. Raymond
  11. You could attach a record with an object's density, and/or, its weight per unit_length. You cannot post the calculation in the OIP without creating a PIO to manage all attributes of volume & density, or length & wt/length, but you can easily (relatively speaking) get those values to display in a Worksheet. A PIO would be a more elegant solution, and the values could easily display in the OIP, but the amount of programming is many times more complicated. Raymond
  12. OK, this is weird. When I wrote the above, I was testing objects on a Design Layer. I just now tested the same objects inside a Symbol Definition. A Layer Plane Object inside a SymDef shows in the OIP as being on the Symbol Definition plane. It displays on the 3D side of the symbol. It tests as 3D, but does not test as Layer Plane. On a Design Layer, the same object will test as 3D, AND as Layer Plane. Bottom Line : Test you code very carefully. Raymond
  13. Hello @sandertb, You can get into a symbol definition with H = Fin3D(GetObject("SymDefName")) which will give you a handle to the first object in a named symbol definition. Then step through the object list with H = vs.NextObj(H) and test each object's 3D-ness with: H = vs.FSActLayer() is3D = vs.GetObjectVariableBoolean(H, 650) # 3D You may have to make a decision how to treat Layer Plane objects and 3D Plane (2D Planar) objects. Technically, Layer Plane objects which look like 2D objects, are considered 3D by the ObjVar_650 test, as are 2D Planar objects. # This will keep Screen & Layer Plane (Symbol Definition Plane) objects, and exclude "classic" 3D objects (Extrudes, Sweeps, 3D Lock, 3D Polys, Solids, etc.) H = vs.FSActLayer() is3D = vs.GetObjectVariableBoolean(H, 650) and not vs.GetObjectVariableBoolean(H, 1161) # 3D and not Planar Use ObjVars: 651 for 2D; 650 for 3D; 1160 for Screen Plane; 1161 for Planar; 1162 for Layer Plane testing. You may have to craft the logic that filters out exactly what you don't want. When you decide to delete an object, make sure you get your next object handle FIRST, before you delete anything. Additionally, you can use ForEachObjectInList() to step through a symbol's elements, but that tutorial is longer. HTH, Raymond PS - There are no simple questions, and fewer simple answers.
  14. Now that would take all the fun out of our late nights, wouldn't it? Do you think Sam's ears are burning, yet?
  15. @Pat Stanford, OK, I see what you mean, but that behavior only applies to menu commands Send Forward and Send Backward. Menu commands Send to Front and Send to Back still work "the old fashioned way." However, from a script, HMoveForward() and HMoveBackward(), work by adjusting the stacking order of the object list, regardless of visible overlapping. I assume @Sam Jones is wanting to use a script to do his dirty work, but if he is tempted to use "DoMenuTextByName('Send Forward', 0)", he's all yours, and I shall remain politely silent. Raymond PS - Whenever the behavior changed for menu commands Send Forward and Send Backward, it has been longer than that that I have used either of those commands. Menu commands Send to Front and Send to Back, I use daily. It's interesting how habits get engrained.
  16. Hi @Pat Stanford, I don't think this has ever changed. If it had, a lot of the scripts I've written over the years would have failed miserably. If you use HMoveForward() or HMoveBackward(), they will change the stacking order whether you move an object one position, or all the way to the front or back. Overlapping objects was never a condition of how the functions work. It is true however, that you won't perceive a difference of a changed stacking order if objects don't overlap. Of course, if you are referring to another way to, as you say above, "Send Back/Send Forward", then I may have completely misunderstood and I will gladly ingest this post if I did. Raymond
  17. @Sam Jones, If Kevin Linzey's method doesn't work, you can build an array of layer handles, stored in order of course. Then use GetLayer(objHnd) to get an object's layer handle. To compare two objects, get their layer handles and search the array of layer handles. The object with the higher array index number is on top. Tedious, but doable. If you need more help, you know where to find me. Raymond
  18. Reshaper can give you this capability, and quite a bit more. DM me for more info if interested. Raymond
  19. Many numbers on the VW Forum are expressed in a condensed form, such as the number of Total Topics – 80.7k, or Total Posts – 412.3k, or the number of posts in the sub-forum Troubleshooting – 41.4k. It would be nice if a condensed number would expand to its exact value when you hover your cursor over it for a second or two, as happens when you hover over a date or time and you see the exact date and time of an event – Joined "1 hour ago" expands to "6/3/2022 @ 7:46 PM." (Welcome @kma3) My real curiosity is to know how many Posts and the Reputation @Pat Stanford really has. Currently if you hover over his avatar, you can only ballpark it at Posts = 9.2k and Reputation = 2.4k. Surely, it would be nice to know exactly how well he is doing. I bet even @Pat Stanford would like to know. The fact it can be done for dates and times leads me to believe it can be done for any number displayed in a compressed format. Thank you, Raymond Mullin
  20. I can neither confirm nor deny my ignorance on the matter of Classes as observable resources in other files.
  21. Sorry @Pat Stanford, I do not, but that's because I've never tired. I don't know if it's possible or not. Raymond
  22. For some unknown reason, to me at least, when processing a text block with 3 or more point sizes, the above procedure gets very close to achieving the proper text length after scaling, but not the exact length. It's slightly long. I did achieve acceptable perfection by repeating the process of scaling a second time. If you need more input on how to do this, write back. Raymond
  23. OK, not as hard as I originally imagined. You just have to scale each character's size by the same amount, and the scale factor is the (existing text length) / (unwrapped text length). Then use a loop to get each characters's size and scale each one to a new size. The secret sauce is knowing how to set the TextWrap and TightFill attributes. The rest is easy peasy. PROCEDURE xxx; { Scale a wrapped text block to fit in the same box on one line. } { 2 Jun 2022 - Raymond Mullin } VAR H :Handle; I :Integer; TxtBoxW, TxtWid, SF, ChSz :Real; BEGIN H := FSActLayer; TxtBoxW := GetTextWidth(H); { target size } SetTextWrap(H, False); { clear Text Wrap } SetObjectVariableBoo(H, 684, False); { clear Tight Fill } TxtWid := GetTextWidth(H); { full length of text } SF := TxtBoxW / TxtWid; { scale factor } for I := 0 to GetTextLength(H) do begin ChSz := GetTextSize(H, I); { individual character size } SetTextSize(H, I, 1, ChSz * SF); { new character size } end; { for } SysBeep; END; Run(xxx); Like Pat, I leave it to you to Pythonize it. Raymond
  24. If the point size is uniform through the entire block, the scaling formula is quite easy to achieve a known length. If you have mixed character sizes throughout the block, and potentially mixed font faces, you will have to build a dynamic array of each character and store its size and fontID, calculate the scale factor needed to change the block length to the desired size, then scale each character individually to achieve the overall desired length. Doable, but tedious. And who said HS algebra class was a waste of time? Raymond
×
×
  • Create New...