public void generateStairProfile() { AXTurtle t = new AXTurtle(); t.dir(90); t.mov(start, 0); int loops = (topStep) ? steps : steps - 1; for (int i = 0; i < loops; i++) { t.fwd(actual_riser); t.right(actual_tread); } t.back(rise); t.path.Reverse(); if (P_Stair_Profile != null) { P_Stair_Profile.paths = new Paths(); P_Stair_Profile.paths.Add(t.path); } }
// SHAPE :: GENERATE public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool isReplica) { //if (Archimatix.doDebug) //Debug.Log ("===> [" + parametricObject.Name + "] generate " + isReplica); if (!parametricObject.isActive) { P_Output.paths = null; P_Output.polyTree = null; return(null); } AXTurtle t = new AXTurtle(); if (parametricObject.code != null) { parametricObject.executeCodeBloc(new List <string>(parametricObject.code.Split("\n"[0])), t); } // if (t.paths.Count == 1) // { // if (! Clipper.Orientation(t.paths[0])) // t.paths[0].Reverse(); // // } t.createBasePolyTreeFromDescription(); AXParameter isClosedP = parametricObject.getParameter("isClosed"); if (isClosedP == null) { isClosedP = parametricObject.getParameter("isclosed"); } if (isClosedP != null) { t.s.isClosed = isClosedP.boolval; } t.s.breakAngle = parametricObject.floatValue("breakAngle"); parametricObject.transMatrix = localMatrix; //Matrix4x4.TRS(new Vector3(transX, transY, 0), Quaternion.Euler(0, 0, rotZ), new Vector3(1,1,1)); // could make more efficient // by resetting output on deserialize using this? AXParameter output = P_Output; if (P_Output != null) { P_Output.spline = t.s; P_Output.polyTree = null; P_Output.controlPaths = t.paths; // not to be altered in base postprocessing for offset and wallthick if (scaleX != 1 || scaleY != 1) { P_Output.transformedButUnscaledOutputPaths = transformPaths(output.controlPaths, localUnscaledMatrix); } else { P_Output.transformedButUnscaledOutputPaths = null; } if (P_Output.offset != 0) { P_Output.transformedAndScaledButNotOffsetdOutputPaths = transformPaths(output.controlPaths, localMatrix); } else { P_Output.transformedAndScaledButNotOffsetdOutputPaths = null; } P_Output.transformedControlPaths = transformPaths(output.controlPaths, localMatrix); //output.getTransformedControlPaths(); P_Output.paths = transformPaths(output.controlPaths, localMatrix); // output.getTransformedControlPaths(); // may be altered before generate is over... } //Debug.Log (t.s.toString()); //Pather.printPaths(P_Output.paths); base.generate(false, initiator_po, isReplica); // calculateBounds(); // adjustWorldMatrices(); return(null); }
// GENERATE LATHE // The only thing a Lathe Node does is prepare a circular Section. Otherwise it is simple a PlanSweep. public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool renderToOutputParameter) { if (parametricObject == null || !parametricObject.isActive) { return(null); } // RESULTING MESHES ax_meshes = new List <AXMesh>(); preGenerate(); // PLAN - is an arc or circle // generate the plane shape. A circle at .5 radius AXParameter plan_p = new AXParameter(); plan_p.Parent = parametricObject; plan_p.Type = AXParameter.DataType.Shape; plan_p.paths = new Paths(); float actingRadius = radius + MIN_RAD; //Debug.Log("actingRadius="+actingRadius); int msegs = Mathf.Max(1, Mathf.FloorToInt(((float)segs * parametricObject.model.segmentReductionFactor))); if (snappedSweepAngle == 360) { plan_p.paths.Add(AXTurtle.Circle(actingRadius, msegs)); plan_p.shapeState = ShapeState.Closed; } else { plan_p.paths.Add(AXTurtle.Arc(actingRadius, 0, snappedSweepAngle, msegs)); plan_p.shapeState = ShapeState.Open; } //plan_p.breakGeom = 10; plan_p.breakNorm = (faceted ? 10 : 135); plan_p.breakGeom = (continuousU ? 100 : 10); // In order to conceptualize the section as at a vert rather than the normal case for PlanSweep where it is on a length, // shift the section out by: dx = R ( 1 - cos(ß/2)) // http://www.archimatix.com/geometry/compensating-for-plansweep-in-a-lathe-mesher float beta = snappedSweepAngle / segs; float dx = actingRadius * (1 - Mathf.Cos(Mathf.Deg2Rad * beta / 2)); //Debug.Log("actingRadius="+actingRadius+", beta="+beta+", dx="+dx); ShiftRadMatrix = Matrix4x4.TRS(new Vector3(-MIN_RAD + dx, 0, 0), Quaternion.identity, Vector3.one); // SECTION // The plan may have multiple paths. Each may generate a separate GO. if (P_Section == null || sectionSrc_p == null || !sectionSrc_p.parametricObject.isActive) { return(null); } P_Section.polyTree = null; P_Section.thickness = 0; P_Section.offset = 0; AXShape.thickenAndOffset(ref P_Section, sectionSrc_p); //Debug.Log(parametricObject.Name); //Debug.Log(ShiftRadMatrix); if (P_Section.polyTree != null) { AX.Generators.Generator2D.transformPolyTree(P_Section.polyTree, ShiftRadMatrix); } else { P_Section.paths = AX.Generators.Generator2D.transformPaths(P_Section.paths, ShiftRadMatrix); } GameObject retGO = null; if (makeGameObjects && P_Section.polyTree == null && P_Section.paths != null && P_Section.paths.Count > 1) { //Debug.Log("make one for each section"); retGO = ArchimatixUtils.createAXGameObject(parametricObject.Name, parametricObject); for (int i = 0; i < P_Section.paths.Count; i++) { AXParameter tmpSecP = new AXParameter(); tmpSecP.shapeState = ShapeState.Open; tmpSecP.parametricObject = parametricObject; Paths tmpPaths = new Paths(); tmpPaths.Add(P_Section.paths[i]); tmpSecP.paths = tmpPaths; GameObject tmpObj = generateFirstPass(initiator_po, makeGameObjects, plan_p, tmpSecP, ShiftRadMatrix, renderToOutputParameter); tmpObj.transform.parent = retGO.transform; } } else { retGO = generateFirstPass(initiator_po, makeGameObjects, plan_p, P_Section, ShiftRadMatrix, renderToOutputParameter); } // FINISH AX_MESHES parametricObject.finishMultiAXMeshAndOutput(ax_meshes, renderToOutputParameter); // FINISH BOUNDING setBoundaryFromAXMeshes(ax_meshes); if (P_Section.polyTree != null) { AX.Generators.Generator2D.transformPolyTree(P_Section.polyTree, ShiftRadMatrix.inverse); } //else // P_Section.paths = AX.Generators.Generator2D.transformPaths(P_Section.paths, ShiftRadMatrix); return(retGO); }
// GENERATE EXTRUDE public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool renderToOutputParameter) { //Debug.Log ("===> [" + parametricObject.Name + "] EXTRUDE generate ... MAKE_GAME_OBJECTS="+makeGameObjects); if (parametricObject == null || !parametricObject.isActive) { return(null); } // RESULTING MESHES ax_meshes = new List <AXMesh>(); //Debug.Log(" ******** A "); preGenerate(); // PLAN - // The plan may have multiple paths. Each may generate a separate GO. if (P_Plan == null || planSrc_p == null || !planSrc_p.parametricObject.isActive) { return(null); } //Debug.Log(" ******** B " + planSrc_p.parametricObject.Name + "." + planSrc_p.Name); // Offset is bevel and !bevelOut float originalOffset = P_Plan.offset; // set back by the max bevel - later consider taper and lip.... if (!bevelOut) { /* * float bevelMax = (bevelTop > bevelBottom) ? bevelTop : bevelBottom; * * if (bevelMax > 0 ) * { * offsetModified -= bevelMax; * //P_Plan.joinType = JoinType.jtMiter; * } */ P_Plan.offset -= (bevelBottom > bevelTop) ? bevelBottom : bevelTop; } // Splitting concave shapes? // THis is a pecial case. An ssumption is mad of no holes // so that we can deal only with paths. if (parametricObject.splitConcaveShapes) //P_Plan.offset != 0) { // SPLIT INTO CONCAVES ** ** ** ** ** ** if no holes, and makeConcave, Paths paths; AXParameter tmpSrc = (!renderToOutputParameter && P_Plan.Dependents != null) ? P_Plan : planSrc_p; if (tmpSrc.polyTree != null) { paths = Clipper.PolyTreeToPaths(tmpSrc.polyTree); } else { paths = tmpSrc.paths; } //Pather.printPaths(P_Plan.paths); if (paths != null) { P_Plan.paths = new Paths(); foreach (Path path in paths) { Paths splitPaths = Pather.splitIntoConvexPaths(path); splitPaths = Pather.offset(splitPaths, P_Plan.offset); P_Plan.paths.AddRange(splitPaths); } } P_Plan.polyTree = null; // SPLIT INTO CONCAVES ** ** ** ** ** ** ** ** if no holes, and makeConcave, } else { //Debug.Log("A: "+planSrc_p.paths[0].Count); P_Plan.polyTree = null; // Debug.Log("EXTRUED " + parametricObject.Name); // Pather.printPaths(P_Plan.paths); if (!renderToOutputParameter && P_Plan.Dependents != null) { // Some Replicant has set the paths of this Plan_P manually AXShape.thickenAndOffset(ref P_Plan, P_Plan); } else { AXShape.thickenAndOffset(ref P_Plan, planSrc_p); } } P_Plan.offset = originalOffset; //Debug.Log("B: " +P_Plan.paths[0].Count); // DEFAULT SECTION -- USING BI_CHAMFER_SIDEflipX Path sectionPath = new Path(); sectionPath = AXTurtle.BiChamferSide(extrude, bevelTop, bevelBottom, bevelSegs, true, taper, lipTop, lipBottom, lipEdge, lipEdgeBottom, segs); AXParameter sec_p = new AXParameter(); sec_p.Parent = parametricObject; sec_p.parametricObject = parametricObject; sec_p.Type = AXParameter.DataType.Shape; sec_p.shapeState = ShapeState.Open; sec_p.paths = new Paths(); sec_p.paths.Add(sectionPath); if (parametricObject.boolValue("Bevel Hard Edge")) { sec_p.breakGeom = 0; sec_p.breakNorm = 0; } //StopWatch sw = new StopWatch(); //Debug.Log("Extrude ===================== "); GameObject retGO = generateFirstPass(initiator_po, makeGameObjects, P_Plan, sec_p, Matrix4x4.identity, renderToOutputParameter); //Debug.Log("Extrude Done ===================== " + sw.duration()); // FINISH AX_MESHES parametricObject.finishMultiAXMeshAndOutput(ax_meshes, true); //renderToOutputParameter); // FINISH BOUNDING setBoundaryFromAXMeshes(ax_meshes); //Debug.Log("Extrude: "+ parametricObject.bounds); return(retGO); }
// GENERATE EXTRUDE public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool renderToOutputParameter) { //Debug.Log ("===> [" + parametricObject.Name + "] EXTRUDE generate ... MAKE_GAME_OBJECTS="+makeGameObjects); if (parametricObject == null || !parametricObject.isActive) { return(null); } // RESULTING MESHES ax_meshes = new List <AXMesh>(); preGenerate(); // PLAN - // The plan may have multiple paths. Each may generate a separate GO. if (P_Plan == null || planSrc_p == null || !planSrc_p.parametricObject.isActive) { return(null); } // Offset is bevel and !bevelOut float originalOffset = P_Plan.offset; // set back by the max bevel - later consider taper and lip.... if (!bevelOut) { /* * float bevelMax = (bevelTop > bevelBottom) ? bevelTop : bevelBottom; * * if (bevelMax > 0 ) * { * offsetModified -= bevelMax; * //P_Plan.joinType = JoinType.jtMiter; * } */ P_Plan.offset -= (bevelBottom > bevelTop) ? bevelBottom : bevelTop; } //Debug.Log("A: "+planSrc_p.paths[0].Count); P_Plan.polyTree = null; AXShape.thickenAndOffset(ref P_Plan, planSrc_p); P_Plan.offset = originalOffset; //Debug.Log("B: " +P_Plan.paths[0].Count); // DEFAULT SECTION -- USING BI_CHAMFER_SIDEflipX Path sectionPath = new Path(); sectionPath = AXTurtle.BiChamferSide(extrude, bevelTop, bevelBottom, bevelSegs, true, taper, lipTop, lipBottom, lipEdge, lipEdgeBottom, segs); AXParameter sec_p = new AXParameter(); sec_p.Parent = parametricObject; sec_p.parametricObject = parametricObject; sec_p.Type = AXParameter.DataType.Shape; sec_p.shapeState = ShapeState.Open; sec_p.paths = new Paths(); sec_p.paths.Add(sectionPath); if (parametricObject.boolValue("Bevel Hard Edge")) { sec_p.breakGeom = 0; sec_p.breakNorm = 0; } //StopWatch sw = new StopWatch(); //Debug.Log("Extrude ===================== "); GameObject retGO = generateFirstPass(initiator_po, makeGameObjects, P_Plan, sec_p, Matrix4x4.identity, renderToOutputParameter); //Debug.Log("Extrude Done ===================== " + sw.duration()); // FINISH AX_MESHES parametricObject.finishMultiAXMeshAndOutput(ax_meshes, renderToOutputParameter); // FINISH BOUNDING setBoundaryFromAXMeshes(ax_meshes); //Debug.Log("Extrude: "+ parametricObject.bounds); return(retGO); }
// GENERATE WINWALL public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool renderToOutputParameter) { if (parametricObject == null || !parametricObject.isActive) { return(null); } //Debug.Log("PlanSweep::generate()"); // RESULTING MESHES ax_meshes = new List <AXMesh>(); preGenerate(); // PLAN // The plan may have multiple paths. Each may generate a separate GO. if (P_Plan == null) { return(null); } planSrc_p = getUpstreamSourceParameter(P_Plan); planSrc_po = (planSrc_p != null) ? planSrc_p.parametricObject : null; if (planSrc_p == null || !planSrc_p.parametricObject.isActive) { return(null); } planIsClosed = (P_Plan.hasThickness || P_Plan.shapeState == ShapeState.Closed) ? true : false; P_Plan.polyTree = null; Paths planPaths = planSrc_p.getPaths(); Path planPath = planPaths[0]; Spline planSpline = new Spline(planPath, planIsClosed, P_Plan.breakGeom, P_Plan.breakNorm); Paths offsetPaths = Pather.wallOffsets(planSpline, .5f, .5f); Pather.printPaths(offsetPaths); // each path, step through and mak a rectangle // segment wide and height and then subtract windows. //Then make poly and add to combiner Path window = AXTurtle.Rectangle(1, 1, false); //window.Reverse(); Pather.shiftPath(window, new IntPoint(10000, 5000)); Debug.Log("=========="); Pather.printPath(window); Pather rightPather = new Pather(offsetPaths[0]); int[] rightLengths = rightPather.segment_lengths; for (int i = 0; i < rightLengths.Length; i++) { Debug.Log(rightLengths[i]); int next_i = (i == rightLengths.Length - 1) ? 0 : i + 1; Path rect = AXTurtle.Rectangle(rightLengths[next_i] / 10000f, 3, false); Clipper c = new Clipper(); c.AddPath(rect, PolyType.ptSubject, true); // fenestration c.AddPath(window, PolyType.ptClip, true); AXClipperLib.PolyTree polytree = new AXClipperLib.PolyTree(); c.Execute(ClipType.ctDifference, polytree, PolyFillType.pftNonZero, PolyFillType.pftNonZero); Paths pathResult = Clipper.PolyTreeToPaths(polytree); Pather.printPaths(pathResult); Mesh mesh = AXPolygon.triangulate(polytree, new AXTexCoords()); Matrix4x4 wallm = Matrix4x4.TRS(new Vector3(offsetPaths[0][i].X / 10000f, 0, offsetPaths[0][i].Y / 10000f), Quaternion.Euler(-90, planSpline.edgeRotations[i], 0), Vector3.one); ax_meshes.Add(new AXMesh(mesh, wallm)); } parametricObject.finishMultiAXMeshAndOutput(ax_meshes, renderToOutputParameter); // FINISH BOUNDING setBoundaryFromAXMeshes(ax_meshes); if (makeGameObjects) { return(parametricObject.makeGameObjectsFromAXMeshes(ax_meshes)); } return(null); }